Merge pull request #1679 from amarjeetkapoor1/parameterASTmaster
Parameter now added in AST
This commit is contained in:
commit
7adb56affe
103 changed files with 1726 additions and 1650 deletions
50
openscad.pro
50
openscad.pro
|
|
@ -205,14 +205,6 @@ CONFIG(mingw-cross-env)|CONFIG(mingw-cross-env-shared) {
|
|||
include(mingw-cross-env.pri)
|
||||
}
|
||||
|
||||
win* {
|
||||
FLEXSOURCES = src/lexer.l
|
||||
BISONSOURCES = src/parser.y
|
||||
} else {
|
||||
LEXSOURCES += src/lexer.l
|
||||
YACCSOURCES += src/parser.y
|
||||
}
|
||||
|
||||
FLEX = src/comment_lexer.l
|
||||
BISON = src/comment_parser.y
|
||||
|
||||
|
|
@ -262,8 +254,32 @@ FORMS += src/MainWindow.ui \
|
|||
src/launchingscreen.ui \
|
||||
src/LibraryInfoDialog.ui \
|
||||
|
||||
HEADERS += src/typedefs.h \
|
||||
src/version_check.h \
|
||||
# AST nodes
|
||||
win* {
|
||||
FLEXSOURCES = src/lexer.l
|
||||
BISONSOURCES = src/parser.y
|
||||
} else {
|
||||
LEXSOURCES += src/lexer.l
|
||||
YACCSOURCES += src/parser.y
|
||||
}
|
||||
|
||||
HEADERS += src/AST.h \
|
||||
src/ModuleInstantiation.h \
|
||||
src/Package.h \
|
||||
src/Assignment.h \
|
||||
src/expression.h \
|
||||
src/function.h \
|
||||
src/module.h \
|
||||
src/UserModule.h
|
||||
|
||||
SOURCES += src/AST.cc \
|
||||
src/ModuleInstantiation.cc \
|
||||
src/expr.cc \
|
||||
src/function.cc \
|
||||
src/module.cc \
|
||||
src/UserModule.cc
|
||||
|
||||
HEADERS += src/version_check.h \
|
||||
src/ProgressWidget.h \
|
||||
src/parsersettings.h \
|
||||
src/renderer.h \
|
||||
|
|
@ -284,6 +300,8 @@ HEADERS += src/typedefs.h \
|
|||
src/AboutDialog.h \
|
||||
src/FontListDialog.h \
|
||||
src/FontListTableView.h \
|
||||
src/GroupModule.h \
|
||||
src/FileModule.h \
|
||||
src/builtin.h \
|
||||
src/calc.h \
|
||||
src/context.h \
|
||||
|
|
@ -295,15 +313,12 @@ HEADERS += src/typedefs.h \
|
|||
src/dxfdata.h \
|
||||
src/dxfdim.h \
|
||||
src/export.h \
|
||||
src/expression.h \
|
||||
src/stackcheck.h \
|
||||
src/function.h \
|
||||
src/exceptions.h \
|
||||
src/grid.h \
|
||||
src/hash.h \
|
||||
src/highlighter.h \
|
||||
src/localscope.h \
|
||||
src/module.h \
|
||||
src/feature.h \
|
||||
src/node.h \
|
||||
src/csgnode.h \
|
||||
|
|
@ -330,9 +345,8 @@ HEADERS += src/typedefs.h \
|
|||
src/value.h \
|
||||
src/progress.h \
|
||||
src/editor.h \
|
||||
src/visitor.h \
|
||||
src/NodeVisitor.h \
|
||||
src/state.h \
|
||||
src/traverser.h \
|
||||
src/nodecache.h \
|
||||
src/nodedumper.h \
|
||||
src/ModuleCache.h \
|
||||
|
|
@ -381,13 +395,11 @@ SOURCES += src/version_check.cc \
|
|||
src/Camera.cc \
|
||||
src/handle_dep.cc \
|
||||
src/value.cc \
|
||||
src/expr.cc \
|
||||
src/stackcheck.cc \
|
||||
src/assignment.cc \
|
||||
src/annotation.cc \
|
||||
src/func.cc \
|
||||
src/localscope.cc \
|
||||
src/module.cc \
|
||||
src/feature.cc \
|
||||
src/node.cc \
|
||||
src/context.cc \
|
||||
|
|
@ -428,7 +440,7 @@ SOURCES += src/version_check.cc \
|
|||
src/LibraryInfo.cc \
|
||||
\
|
||||
src/nodedumper.cc \
|
||||
src/traverser.cc \
|
||||
src/NodeVisitor.cc \
|
||||
src/GeometryEvaluator.cc \
|
||||
src/ModuleCache.cc \
|
||||
src/GeometryCache.cc \
|
||||
|
|
@ -449,6 +461,8 @@ SOURCES += src/version_check.cc \
|
|||
\
|
||||
src/grid.cc \
|
||||
src/hash.cc \
|
||||
src/GroupModule.cc \
|
||||
src/FileModule.cc \
|
||||
src/builtin.cc \
|
||||
src/calc.cc \
|
||||
src/export.cc \
|
||||
|
|
|
|||
3
src/AST.cc
Normal file
3
src/AST.cc
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#include "AST.h"
|
||||
|
||||
Location Location::NONE(0, 0, 0, 0);
|
||||
33
src/AST.h
Normal file
33
src/AST.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
class Location {
|
||||
public:
|
||||
Location(int firstLine, int firstCol, int lastLine, int lastCol)
|
||||
: first_line(firstLine), first_col(firstCol), last_line(lastLine), last_col(lastCol) {
|
||||
}
|
||||
|
||||
int firstLine() const { return first_line; }
|
||||
int firstColumn() const { return first_col; }
|
||||
int lastLine() const { return last_line; }
|
||||
int lastColumn() const { return last_col; }
|
||||
|
||||
|
||||
static Location NONE;
|
||||
private:
|
||||
int first_line;
|
||||
int first_col;
|
||||
int last_line;
|
||||
int last_col;
|
||||
};
|
||||
|
||||
class ASTNode
|
||||
{
|
||||
public:
|
||||
ASTNode(const Location &loc) : loc(loc) {}
|
||||
virtual ~ASTNode() {}
|
||||
|
||||
Location location() const { return loc; }
|
||||
|
||||
protected:
|
||||
Location loc;
|
||||
};
|
||||
70
src/Assignment.h
Normal file
70
src/Assignment.h
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include "value.h"
|
||||
|
||||
#include "AST.h"
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
class Annotation;
|
||||
|
||||
typedef std::map<const std::string, Annotation *> AnnotationMap;
|
||||
|
||||
typedef std::vector<Annotation> AnnotationList;
|
||||
|
||||
class Assignment : public ASTNode
|
||||
{
|
||||
public:
|
||||
Assignment(std::string name, const Location &loc)
|
||||
: ASTNode(loc), name(name) { }
|
||||
Assignment(std::string name,
|
||||
shared_ptr<class Expression> expr = shared_ptr<class Expression>(),
|
||||
const Location &loc = Location::NONE)
|
||||
: ASTNode(loc), name(name), expr(expr) { }
|
||||
|
||||
std::string name;
|
||||
shared_ptr<class Expression> expr;
|
||||
typedef std::vector<Assignment> AssignmentList;
|
||||
|
||||
virtual void add_annotations(AnnotationList *annotations);
|
||||
virtual void add_annotation(Annotation *annotations);
|
||||
|
||||
virtual bool has_annotations() const;
|
||||
virtual const Annotation * annotation(const std::string &name) const;
|
||||
|
||||
protected:
|
||||
AnnotationMap annotations;
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<Assignment> AssignmentList;
|
||||
|
||||
class Annotation
|
||||
{
|
||||
protected:
|
||||
Annotation(const std::string name, const AssignmentList assignments, const AssignmentList args);
|
||||
|
||||
public:
|
||||
virtual ~Annotation();
|
||||
|
||||
void dump();
|
||||
const std::string & get_name();
|
||||
virtual ValuePtr evaluate(class Context *ctx, const std::string& var) const;
|
||||
|
||||
Annotation& operator=(const Annotation&);
|
||||
|
||||
static const Annotation * create(const std::string name, const AssignmentList assignments);
|
||||
|
||||
//private:
|
||||
std::string name;
|
||||
/** Defines the names and values parsed from the script */
|
||||
AssignmentList assignments;
|
||||
private:
|
||||
/** Defines the names of the positional parameters */
|
||||
AssignmentList args;
|
||||
};
|
||||
42
src/BaseVisitable.h
Normal file
42
src/BaseVisitable.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// FIXME: Default constructor Response()
|
||||
enum Response {ContinueTraversal, AbortTraversal, PruneTraversal};
|
||||
|
||||
class BaseVisitor
|
||||
{
|
||||
public:
|
||||
virtual ~BaseVisitor() {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Visitor
|
||||
{
|
||||
public:
|
||||
virtual Response visit(class State &state, const T&) = 0;
|
||||
};
|
||||
|
||||
class BaseVisitable
|
||||
{
|
||||
public:
|
||||
virtual ~BaseVisitable() {}
|
||||
virtual Response accept(class State&, BaseVisitor&) const = 0;
|
||||
protected:
|
||||
template <class T>
|
||||
static Response acceptImpl(class State &state, const T &node, BaseVisitor &visitor) {
|
||||
if (Visitor<T> *p = dynamic_cast<Visitor<T>*>(&visitor)) {
|
||||
return p->visit(state, node);
|
||||
}
|
||||
// FIXME: If we want to allow for missing nodes in visitors, we need
|
||||
// to handle it here, e.g. by calling some handler.
|
||||
// See e.g. page 225 of Alexandrescu's "Modern C++ Design"
|
||||
return AbortTraversal;
|
||||
}
|
||||
};
|
||||
|
||||
#define VISITABLE() \
|
||||
virtual Response accept(class State &state, BaseVisitor &visitor) const { \
|
||||
return acceptImpl(state, *this, visitor); \
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
#include "CSGTreeEvaluator.h"
|
||||
#include "visitor.h"
|
||||
#include "state.h"
|
||||
#include "csgops.h"
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "csgnode.h"
|
||||
#include "transformnode.h"
|
||||
#include "colornode.h"
|
||||
|
|
@ -30,8 +30,7 @@
|
|||
|
||||
shared_ptr<CSGNode> CSGTreeEvaluator::buildCSGTree(const AbstractNode &node)
|
||||
{
|
||||
Traverser evaluate(*this, node, Traverser::PRE_AND_POSTFIX);
|
||||
evaluate.execute();
|
||||
this->traverse(node);
|
||||
|
||||
shared_ptr<CSGNode> t(this->stored_term[node.index()]);
|
||||
if (t) {
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@
|
|||
#include <list>
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include "visitor.h"
|
||||
#include "NodeVisitor.h"
|
||||
#include "memory.h"
|
||||
#include "csgnode.h"
|
||||
|
||||
class CSGTreeEvaluator : public Visitor
|
||||
class CSGTreeEvaluator : public NodeVisitor
|
||||
{
|
||||
public:
|
||||
CSGTreeEvaluator(const class Tree &tree, class GeometryEvaluator *geomevaluator = NULL)
|
||||
|
|
|
|||
185
src/FileModule.cc
Normal file
185
src/FileModule.cc
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* OpenSCAD (www.openscad.org)
|
||||
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
|
||||
* Marius Kintel <marius@kintel.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* As a special exception, you have permission to link this program
|
||||
* with the CGAL library and distribute executables, as long as you
|
||||
* follow the requirements of the GNU GPL in regard to all of the
|
||||
* software in the executable aside from CGAL.
|
||||
*
|
||||
* 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 "FileModule.h"
|
||||
#include "ModuleCache.h"
|
||||
#include "node.h"
|
||||
#include "printutils.h"
|
||||
#include "exceptions.h"
|
||||
#include "modcontext.h"
|
||||
#include "parsersettings.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
namespace fs = boost::filesystem;
|
||||
#include "boosty.h"
|
||||
#include "FontCache.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
FileModule::~FileModule()
|
||||
{
|
||||
delete context;
|
||||
}
|
||||
|
||||
std::string FileModule::dump(const std::string &indent, const std::string &name) const
|
||||
{
|
||||
return scope.dump(indent);
|
||||
}
|
||||
|
||||
void FileModule::registerUse(const std::string path) {
|
||||
std::string extraw = boosty::extension_str(fs::path(path));
|
||||
std::string ext = boost::algorithm::to_lower_copy(extraw);
|
||||
|
||||
if ((ext == ".otf") || (ext == ".ttf")) {
|
||||
if (fs::is_regular(path)) {
|
||||
FontCache::instance()->register_font_file(path);
|
||||
} else {
|
||||
PRINTB("ERROR: Can't read font with path '%s'", path);
|
||||
}
|
||||
} else {
|
||||
usedlibs.insert(path);
|
||||
}
|
||||
}
|
||||
|
||||
void FileModule::registerInclude(const std::string &localpath,
|
||||
const std::string &fullpath)
|
||||
{
|
||||
struct stat st;
|
||||
memset(&st, 0, sizeof(struct stat));
|
||||
bool valid = stat(fullpath.c_str(), &st) == 0;
|
||||
IncludeFile inc = {fullpath, valid, st.st_mtime};
|
||||
this->includes[localpath] = inc;
|
||||
}
|
||||
|
||||
bool FileModule::includesChanged() const
|
||||
{
|
||||
for(const auto &item : this->includes) {
|
||||
if (include_modified(item.second)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FileModule::include_modified(const IncludeFile &inc) const
|
||||
{
|
||||
struct stat st;
|
||||
memset(&st, 0, sizeof(struct stat));
|
||||
|
||||
fs::path fullpath = find_valid_path(this->path, inc.filename);
|
||||
bool valid = !fullpath.empty() ? (stat(boosty::stringy(fullpath).c_str(), &st) == 0) : false;
|
||||
|
||||
if (valid && !inc.valid) return true; // Detect appearance of file but not removal
|
||||
if (valid && st.st_mtime > inc.mtime) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Check if any dependencies have been modified and recompile them.
|
||||
Returns true if anything was recompiled.
|
||||
*/
|
||||
bool FileModule::handleDependencies()
|
||||
{
|
||||
if (this->is_handling_dependencies) return false;
|
||||
this->is_handling_dependencies = true;
|
||||
|
||||
bool somethingchanged = false;
|
||||
std::vector<std::pair<std::string,std::string>> updates;
|
||||
|
||||
// If a lib in usedlibs was previously missing, we need to relocate it
|
||||
// by searching the applicable paths. We can identify a previously missing module
|
||||
// as it will have a relative path.
|
||||
for(auto filename : this->usedlibs) {
|
||||
|
||||
bool wasmissing = false;
|
||||
bool found = true;
|
||||
|
||||
// Get an absolute filename for the module
|
||||
if (!boosty::is_absolute(filename)) {
|
||||
wasmissing = true;
|
||||
fs::path fullpath = find_valid_path(this->path, filename);
|
||||
if (!fullpath.empty()) {
|
||||
updates.push_back(std::make_pair(filename, boosty::stringy(fullpath)));
|
||||
filename = boosty::stringy(fullpath);
|
||||
}
|
||||
else {
|
||||
found = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
bool wascached = ModuleCache::instance()->isCached(filename);
|
||||
FileModule *oldmodule = ModuleCache::instance()->lookup(filename);
|
||||
FileModule *newmodule;
|
||||
bool changed = ModuleCache::instance()->evaluate(filename, newmodule);
|
||||
// Detect appearance but not removal of files, and keep old module
|
||||
// on compile errors (FIXME: Is this correct behavior?)
|
||||
if (changed) {
|
||||
PRINTDB(" %s: %p -> %p", filename % oldmodule % newmodule);
|
||||
}
|
||||
somethingchanged |= changed;
|
||||
// Only print warning if we're not part of an automatic reload
|
||||
if (!newmodule && !wascached && !wasmissing) {
|
||||
PRINTB_NOCACHE("WARNING: Failed to compile library '%s'.", filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Relative filenames which were located is reinserted as absolute filenames
|
||||
typedef std::pair<std::string,std::string> stringpair;
|
||||
for(const auto &files : updates) {
|
||||
this->usedlibs.erase(files.first);
|
||||
this->usedlibs.insert(files.second);
|
||||
}
|
||||
this->is_handling_dependencies = false;
|
||||
return somethingchanged;
|
||||
}
|
||||
|
||||
AbstractNode *FileModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||
{
|
||||
assert(evalctx == NULL);
|
||||
|
||||
delete this->context;
|
||||
this->context = new FileContext(*this, ctx);
|
||||
AbstractNode *node = new RootNode(inst);
|
||||
|
||||
try {
|
||||
context->initializeModule(*this);
|
||||
|
||||
// FIXME: Set document path to the path of the module
|
||||
std::vector<AbstractNode *> instantiatednodes = this->scope.instantiateChildren(context);
|
||||
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
||||
}
|
||||
catch (EvaluationException &e) {
|
||||
PRINT(e.what());
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
ValuePtr FileModule::lookup_variable(const std::string &name) const
|
||||
{
|
||||
if (!this->context) return ValuePtr::undefined;
|
||||
return this->context->lookup_variable(name, true);
|
||||
}
|
||||
49
src/FileModule.h
Normal file
49
src/FileModule.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <time.h>
|
||||
|
||||
#include "module.h"
|
||||
#include "value.h"
|
||||
#include "localscope.h"
|
||||
|
||||
class FileModule : public AbstractModule
|
||||
{
|
||||
public:
|
||||
FileModule() : context(nullptr), is_handling_dependencies(false) {}
|
||||
virtual ~FileModule();
|
||||
|
||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx = NULL) const;
|
||||
virtual std::string dump(const std::string &indent, const std::string &name) const;
|
||||
void setModulePath(const std::string &path) { this->path = path; }
|
||||
const std::string &modulePath() const { return this->path; }
|
||||
void registerUse(const std::string path);
|
||||
void registerInclude(const std::string &localpath, const std::string &fullpath);
|
||||
bool includesChanged() const;
|
||||
bool handleDependencies();
|
||||
bool hasIncludes() const { return !this->includes.empty(); }
|
||||
bool usesLibraries() const { return !this->usedlibs.empty(); }
|
||||
bool isHandlingDependencies() const { return this->is_handling_dependencies; }
|
||||
ValuePtr lookup_variable(const std::string &name) const;
|
||||
|
||||
LocalScope scope;
|
||||
typedef std::unordered_set<std::string> ModuleContainer;
|
||||
ModuleContainer usedlibs;
|
||||
private:
|
||||
// Reference to retain the context that was used in the last evaluation
|
||||
mutable class FileContext *context;
|
||||
struct IncludeFile {
|
||||
std::string filename;
|
||||
bool valid;
|
||||
time_t mtime;
|
||||
};
|
||||
|
||||
bool include_modified(const IncludeFile &inc) const;
|
||||
|
||||
typedef std::unordered_map<std::string, struct IncludeFile> IncludeContainer;
|
||||
IncludeContainer includes;
|
||||
bool is_handling_dependencies;
|
||||
std::string path;
|
||||
};
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
#include "GeometryEvaluator.h"
|
||||
#include "traverser.h"
|
||||
#include "Tree.h"
|
||||
#include "GeometryCache.h"
|
||||
#include "CGALCache.h"
|
||||
#include "Polygon2d.h"
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "state.h"
|
||||
#include "offsetnode.h"
|
||||
#include "transformnode.h"
|
||||
|
|
@ -54,8 +54,7 @@ shared_ptr<const Geometry> GeometryEvaluator::evaluateGeometry(const AbstractNod
|
|||
this->root = N;
|
||||
}
|
||||
else {
|
||||
Traverser trav(*this, node, Traverser::PRE_AND_POSTFIX);
|
||||
trav.execute();
|
||||
this->traverse(node);
|
||||
}
|
||||
|
||||
if (!allownef) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "visitor.h"
|
||||
#include "NodeVisitor.h"
|
||||
#include "enums.h"
|
||||
#include "memory.h"
|
||||
#include "Geometry.h"
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
class GeometryEvaluator : public Visitor
|
||||
class GeometryEvaluator : public NodeVisitor
|
||||
{
|
||||
public:
|
||||
GeometryEvaluator(const class Tree &tree);
|
||||
|
|
|
|||
47
src/GroupModule.cc
Normal file
47
src/GroupModule.cc
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* OpenSCAD (www.openscad.org)
|
||||
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
|
||||
* Marius Kintel <marius@kintel.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* As a special exception, you have permission to link this program
|
||||
* with the CGAL library and distribute executables, as long as you
|
||||
* follow the requirements of the GNU GPL in regard to all of the
|
||||
* software in the executable aside from CGAL.
|
||||
*
|
||||
* 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 "GroupModule.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "node.h"
|
||||
#include "builtin.h"
|
||||
#include "evalcontext.h"
|
||||
|
||||
AbstractNode *GroupModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||
{
|
||||
(void)ctx; // avoid unusued parameter warning
|
||||
|
||||
AbstractNode *node = new GroupNode(inst);
|
||||
|
||||
node->children = inst->instantiateChildren(evalctx);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void register_builtin_group()
|
||||
{
|
||||
Builtins::init("group", new GroupModule());
|
||||
}
|
||||
11
src/GroupModule.h
Normal file
11
src/GroupModule.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "module.h"
|
||||
|
||||
class GroupModule : public AbstractModule
|
||||
{
|
||||
public:
|
||||
GroupModule() { }
|
||||
virtual ~GroupModule() { }
|
||||
virtual class AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, class EvalContext *evalctx = NULL) const;
|
||||
};
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
#include "openscad.h"
|
||||
#include "modcontext.h"
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "Tree.h"
|
||||
#include "memory.h"
|
||||
#include "editor.h"
|
||||
|
|
@ -16,6 +17,9 @@
|
|||
#include <QMutex>
|
||||
#include <QTime>
|
||||
#include <QIODevice>
|
||||
#include"Assignment.h"
|
||||
|
||||
extern AssignmentList * parser(const char *text);
|
||||
|
||||
class MainWindow : public QMainWindow, public Ui::MainWindow
|
||||
{
|
||||
|
|
@ -94,6 +98,8 @@ private slots:
|
|||
void consoleOutput(const QString &msg);
|
||||
|
||||
private:
|
||||
void addparameter(const char *fulltext);
|
||||
string getParameter(string fulltext, int loc);
|
||||
void initActionIcon(QAction *action, const char *darkResource, const char *lightResource);
|
||||
void handleFileDrop(const QString &filename);
|
||||
void refreshDocument();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include "ModuleCache.h"
|
||||
#include "module.h"
|
||||
#include "FileModule.h"
|
||||
#include "printutils.h"
|
||||
#include "openscad.h"
|
||||
|
||||
|
|
|
|||
96
src/ModuleInstantiation.cc
Normal file
96
src/ModuleInstantiation.cc
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
#include "ModuleInstantiation.h"
|
||||
#include "evalcontext.h"
|
||||
#include "expression.h"
|
||||
|
||||
#include "boosty.h"
|
||||
|
||||
ModuleInstantiation::~ModuleInstantiation()
|
||||
{
|
||||
}
|
||||
|
||||
IfElseModuleInstantiation::~IfElseModuleInstantiation()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the absolute path to the given filename, unless it's empty.
|
||||
|
||||
NB! This will actually search for the file, to be backwards compatible with <= 2013.01
|
||||
(see issue #217)
|
||||
*/
|
||||
std::string ModuleInstantiation::getAbsolutePath(const std::string &filename) const
|
||||
{
|
||||
if (!filename.empty() && !boosty::is_absolute(fs::path(filename))) {
|
||||
return boosty::absolute(fs::path(this->modpath) / filename).string();
|
||||
}
|
||||
else {
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
|
||||
std::string ModuleInstantiation::dump(const std::string &indent) const
|
||||
{
|
||||
std::stringstream dump;
|
||||
dump << indent;
|
||||
dump << modname + "(";
|
||||
for (size_t i=0; i < this->arguments.size(); i++) {
|
||||
const Assignment &arg = this->arguments[i];
|
||||
if (i > 0) dump << ", ";
|
||||
if (!arg.name.empty()) dump << arg.name << " = ";
|
||||
dump << *arg.expr;
|
||||
}
|
||||
if (scope.numElements() == 0) {
|
||||
dump << ");\n";
|
||||
} else if (scope.numElements() == 1) {
|
||||
dump << ") ";
|
||||
dump << scope.dump("");
|
||||
} else {
|
||||
dump << ") {\n";
|
||||
dump << scope.dump(indent + "\t");
|
||||
dump << indent << "}\n";
|
||||
}
|
||||
return dump.str();
|
||||
}
|
||||
|
||||
std::string IfElseModuleInstantiation::dump(const std::string &indent) const
|
||||
{
|
||||
std::stringstream dump;
|
||||
dump << ModuleInstantiation::dump(indent);
|
||||
dump << indent;
|
||||
if (else_scope.numElements() > 0) {
|
||||
dump << indent << "else ";
|
||||
if (else_scope.numElements() == 1) {
|
||||
dump << else_scope.dump("");
|
||||
}
|
||||
else {
|
||||
dump << "{\n";
|
||||
dump << else_scope.dump(indent + "\t");
|
||||
dump << indent << "}\n";
|
||||
}
|
||||
}
|
||||
return dump.str();
|
||||
}
|
||||
|
||||
AbstractNode *ModuleInstantiation::evaluate(const Context *ctx) const
|
||||
{
|
||||
EvalContext c(ctx, this->arguments, &this->scope);
|
||||
|
||||
#if 0 && DEBUG
|
||||
PRINT("New eval ctx:");
|
||||
c.dump(NULL, this);
|
||||
#endif
|
||||
|
||||
AbstractNode *node = ctx->instantiate_module(*this, &c); // Passes c as evalctx
|
||||
return node;
|
||||
}
|
||||
|
||||
std::vector<AbstractNode*> ModuleInstantiation::instantiateChildren(const Context *evalctx) const
|
||||
{
|
||||
return this->scope.instantiateChildren(evalctx);
|
||||
}
|
||||
|
||||
std::vector<AbstractNode*> IfElseModuleInstantiation::instantiateElseChildren(const Context *evalctx) const
|
||||
{
|
||||
return this->else_scope.instantiateChildren(evalctx);
|
||||
}
|
||||
|
||||
49
src/ModuleInstantiation.h
Normal file
49
src/ModuleInstantiation.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include "AST.h"
|
||||
#include "localscope.h"
|
||||
#include <vector>
|
||||
|
||||
typedef std::vector<class ModuleInstantiation*> ModuleInstantiationList;
|
||||
|
||||
class ModuleInstantiation : public ASTNode
|
||||
{
|
||||
public:
|
||||
ModuleInstantiation(const std::string &name, const AssignmentList &args = AssignmentList(), const std::string &source_path = std::string(), const Location &loc = Location::NONE)
|
||||
: ASTNode(loc), arguments(args), tag_root(false), tag_highlight(false), tag_background(false), modname(name), modpath(source_path) { }
|
||||
virtual ~ModuleInstantiation();
|
||||
|
||||
virtual std::string dump(const std::string &indent) const;
|
||||
class AbstractNode *evaluate(const class Context *ctx) const;
|
||||
std::vector<AbstractNode*> instantiateChildren(const Context *evalctx) const;
|
||||
|
||||
// This is only needed for import() and the deprecated *_extrude() modules
|
||||
const std::string &path() const { return this->modpath; }
|
||||
std::string getAbsolutePath(const std::string &filename) const;
|
||||
|
||||
const std::string &name() const { return this->modname; }
|
||||
bool isBackground() const { return this->tag_background; }
|
||||
bool isHighlight() const { return this->tag_highlight; }
|
||||
bool isRoot() const { return this->tag_root; }
|
||||
|
||||
AssignmentList arguments;
|
||||
LocalScope scope;
|
||||
|
||||
bool tag_root;
|
||||
bool tag_highlight;
|
||||
bool tag_background;
|
||||
protected:
|
||||
std::string modname;
|
||||
std::string modpath;
|
||||
};
|
||||
|
||||
class IfElseModuleInstantiation : public ModuleInstantiation {
|
||||
public:
|
||||
IfElseModuleInstantiation(shared_ptr<class Expression> expr, const std::string &source_path, const Location &loc) : ModuleInstantiation("if", AssignmentList{Assignment("", expr)}, source_path, loc) { }
|
||||
virtual ~IfElseModuleInstantiation();
|
||||
std::vector<AbstractNode*> instantiateElseChildren(const Context *evalctx) const;
|
||||
virtual std::string dump(const std::string &indent) const;
|
||||
|
||||
LocalScope else_scope;
|
||||
};
|
||||
|
||||
|
|
@ -1,26 +1,17 @@
|
|||
#include "traverser.h"
|
||||
#include "visitor.h"
|
||||
#include "node.h"
|
||||
#include "NodeVisitor.h"
|
||||
#include "state.h"
|
||||
#include <algorithm>
|
||||
|
||||
void Traverser::execute()
|
||||
{
|
||||
State state(NULL);
|
||||
traverse(this->root, state);
|
||||
}
|
||||
State NodeVisitor::nullstate(nullptr);
|
||||
|
||||
Response Traverser::traverse(const AbstractNode &node, const State &state)
|
||||
Response NodeVisitor::traverse(const AbstractNode &node, const State &state)
|
||||
{
|
||||
State newstate = state;
|
||||
newstate.setNumChildren(node.getChildren().size());
|
||||
|
||||
Response response = ContinueTraversal;
|
||||
if (traversaltype == PREFIX || traversaltype == PRE_AND_POSTFIX) {
|
||||
newstate.setPrefix(true);
|
||||
newstate.setParent(state.parent());
|
||||
response = node.accept(newstate, this->visitor);
|
||||
}
|
||||
newstate.setPrefix(true);
|
||||
newstate.setParent(state.parent());
|
||||
response = node.accept(newstate, *this);
|
||||
|
||||
// Pruned traversals mean don't traverse children
|
||||
if (response == ContinueTraversal) {
|
||||
|
|
@ -33,12 +24,10 @@ Response Traverser::traverse(const AbstractNode &node, const State &state)
|
|||
|
||||
// Postfix is executed for all non-aborted traversals
|
||||
if (response != AbortTraversal) {
|
||||
if (traversaltype == POSTFIX || traversaltype == PRE_AND_POSTFIX) {
|
||||
newstate.setParent(state.parent());
|
||||
newstate.setPrefix(false);
|
||||
newstate.setPostfix(true);
|
||||
response = node.accept(newstate, this->visitor);
|
||||
}
|
||||
newstate.setParent(state.parent());
|
||||
newstate.setPrefix(false);
|
||||
newstate.setPostfix(true);
|
||||
response = node.accept(newstate, *this);
|
||||
}
|
||||
|
||||
if (response != AbortTraversal) response = ContinueTraversal;
|
||||
|
|
@ -1,13 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include "traverser.h"
|
||||
#include "BaseVisitable.h"
|
||||
#include "node.h"
|
||||
#include "state.h"
|
||||
|
||||
class Visitor
|
||||
class NodeVisitor :
|
||||
public BaseVisitor,
|
||||
public Visitor<class AbstractNode>,
|
||||
public Visitor<class AbstractIntersectionNode>,
|
||||
public Visitor<class AbstractPolyNode>,
|
||||
public Visitor<class GroupNode>,
|
||||
public Visitor<class RootNode>,
|
||||
public Visitor<class LeafNode>,
|
||||
public Visitor<class CgaladvNode>,
|
||||
public Visitor<class CsgOpNode>,
|
||||
public Visitor<class LinearExtrudeNode>,
|
||||
public Visitor<class RotateExtrudeNode>,
|
||||
public Visitor<class ImportNode>,
|
||||
public Visitor<class PrimitiveNode>,
|
||||
public Visitor<class TextNode>,
|
||||
public Visitor<class ProjectionNode>,
|
||||
public Visitor<class RenderNode>,
|
||||
public Visitor<class SurfaceNode>,
|
||||
public Visitor<class TransformNode>,
|
||||
public Visitor<class ColorNode>,
|
||||
public Visitor<class OffsetNode>
|
||||
{
|
||||
public:
|
||||
Visitor() {}
|
||||
virtual ~Visitor() {}
|
||||
NodeVisitor() {}
|
||||
virtual ~NodeVisitor() {}
|
||||
|
||||
Response traverse(const AbstractNode &node, const class State &state = NodeVisitor::nullstate);
|
||||
|
||||
virtual Response visit(class State &state, const class AbstractNode &node) = 0;
|
||||
virtual Response visit(class State &state, const class AbstractIntersectionNode &node) {
|
||||
return visit(state, (const class AbstractNode &)node);
|
||||
|
|
@ -18,7 +42,7 @@ public:
|
|||
virtual Response visit(class State &state, const class GroupNode &node) {
|
||||
return visit(state, (const class AbstractNode &)node);
|
||||
}
|
||||
virtual Response visit(class State &state, const class RootNode &node) {
|
||||
virtual Response visit(class State &state, const RootNode &node) {
|
||||
return visit(state, (const class GroupNode &)node);
|
||||
}
|
||||
virtual Response visit(class State &state, const class LeafNode &node) {
|
||||
|
|
@ -64,4 +88,7 @@ public:
|
|||
return visit(state, (const class AbstractPolyNode &)node);
|
||||
}
|
||||
// Add visit() methods for new visitable subtypes of AbstractNode here
|
||||
|
||||
private:
|
||||
static State nullstate;
|
||||
};
|
||||
20
src/Package.h
Normal file
20
src/Package.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include "AST.h"
|
||||
#include <string>
|
||||
|
||||
class Package : public ASTNode
|
||||
{
|
||||
public:
|
||||
Package() {}
|
||||
virtual ~Package() {}
|
||||
|
||||
void setPath(const std::string &path) { this->_path = path; }
|
||||
const std::string &path() const { return this->_path; }
|
||||
|
||||
LocalScope scope;
|
||||
typedef std::unordered_set<std::string> ModuleContainer;
|
||||
ModuleContainer usedlibs;
|
||||
private:
|
||||
std::string _path;
|
||||
};
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "parameterextractor.h"
|
||||
|
||||
#include "module.h"
|
||||
#include "FileModule.h"
|
||||
#include "modcontext.h"
|
||||
|
||||
ParameterExtractor::ParameterExtractor()
|
||||
|
|
@ -18,7 +18,7 @@ void ParameterExtractor::applyParameters(FileModule *fileModule)
|
|||
}
|
||||
|
||||
for (AssignmentList::iterator it = fileModule->scope.assignments.begin();it != fileModule->scope.assignments.end();it++) {
|
||||
entry_map_t::iterator entry = entries.find((*it).first);
|
||||
entry_map_t::iterator entry = entries.find((*it).name);
|
||||
if (entry == entries.end()) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ void ParameterExtractor::applyParameters(FileModule *fileModule)
|
|||
}
|
||||
}
|
||||
|
||||
void ParameterExtractor::setParameters(const Module *module)
|
||||
void ParameterExtractor::setParameters(const FileModule* module)
|
||||
{
|
||||
if (module == NULL) {
|
||||
return;
|
||||
|
|
@ -43,7 +43,7 @@ void ParameterExtractor::setParameters(const Module *module)
|
|||
continue;
|
||||
}
|
||||
|
||||
const ValuePtr defaultValue = assignment.second.get()->evaluate(&ctx);
|
||||
const ValuePtr defaultValue = assignment.expr.get()->evaluate(&ctx);
|
||||
if (defaultValue->type() == Value::UNDEFINED) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -52,13 +52,13 @@ void ParameterExtractor::setParameters(const Module *module)
|
|||
entryObject->setAssignment(&ctx, &assignment, defaultValue);
|
||||
|
||||
//need to improve structure
|
||||
if(entries.find(assignment.first) == entries.end()){
|
||||
entries[assignment.first] = entryObject;
|
||||
if(entries.find(assignment.name) == entries.end()){
|
||||
entries[assignment.name] = entryObject;
|
||||
}else{
|
||||
if(*entryObject==*entries[assignment.first]){
|
||||
entryObject=entries[assignment.first];
|
||||
if(*entryObject==*entries[assignment.name]){
|
||||
entryObject=entries[assignment.name];
|
||||
}else{
|
||||
entries[assignment.first] = entryObject;
|
||||
entries[assignment.name] = entryObject;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef PARAMETEREXTRACTOR_H
|
||||
#define PARAMETEREXTRACTOR_H
|
||||
|
||||
#include "FileModule.h"
|
||||
#include "parametervirtualwidget.h"
|
||||
|
||||
class ParameterExtractor
|
||||
|
|
@ -14,7 +15,7 @@ protected:
|
|||
public:
|
||||
ParameterExtractor();
|
||||
virtual ~ParameterExtractor();
|
||||
void setParameters(const Module *module);
|
||||
void setParameters(const FileModule* module);
|
||||
void applyParameters(class FileModule *fileModule);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ ParameterObject::ParameterObject()
|
|||
void ParameterObject::applyParameter(class Assignment *assignment){
|
||||
|
||||
ModuleContext ctx;
|
||||
const ValuePtr defaultValue =assignment->second.get()->evaluate(&ctx);
|
||||
const ValuePtr defaultValue =assignment->expr.get()->evaluate(&ctx);
|
||||
|
||||
if( defaultValue->type() == dvt ){
|
||||
assignment->second = shared_ptr<Expression>(new ExpressionConst(value));
|
||||
assignment->expr = shared_ptr<Expression>(new Literal(value));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ int ParameterObject::setValue(const class ValuePtr defaultValue, const class Val
|
|||
}
|
||||
|
||||
void ParameterObject::setAssignment(class Context *ctx, const class Assignment *assignment, const ValuePtr defaultValue){
|
||||
name = assignment->first;
|
||||
name = assignment->name;
|
||||
const Annotation *param = assignment->annotation("Parameter");
|
||||
const ValuePtr values = param->evaluate(ctx, "values");
|
||||
setValue(defaultValue, values);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include "value.h"
|
||||
#include "qtgettext.h"
|
||||
#include "typedefs.h"
|
||||
#include "Assignment.h"
|
||||
#include "expression.h"
|
||||
#include<QString>
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ Preferences *Preferences::instance = NULL;
|
|||
const char * Preferences::featurePropertyName = "FeatureProperty";
|
||||
Q_DECLARE_METATYPE(Feature *);
|
||||
|
||||
class SettingsReader : public Settings::Visitor
|
||||
class SettingsReader : public Settings::SettingsVisitor
|
||||
{
|
||||
QSettings settings;
|
||||
Value getValue(const Settings::SettingsEntry& entry, const std::string& value) const {
|
||||
|
|
@ -90,7 +90,7 @@ class SettingsReader : public Settings::Visitor
|
|||
}
|
||||
};
|
||||
|
||||
class SettingsWriter : public Settings::Visitor
|
||||
class SettingsWriter : public Settings::SettingsVisitor
|
||||
{
|
||||
virtual void handle(Settings::SettingsEntry& entry) const {
|
||||
Settings::Settings *s = Settings::Settings::inst();
|
||||
|
|
|
|||
|
|
@ -24,8 +24,7 @@ const std::string &Tree::getString(const AbstractNode &node) const
|
|||
this->nodecache.clear();
|
||||
this->nodeidcache.clear();
|
||||
NodeDumper dumper(this->nodecache, false);
|
||||
Traverser trav(dumper, *this->root_node, Traverser::PRE_AND_POSTFIX);
|
||||
trav.execute();
|
||||
dumper.traverse(*this->root_node);
|
||||
assert(this->nodecache.contains(*this->root_node) &&
|
||||
"NodeDumper failed to create a cache");
|
||||
}
|
||||
|
|
|
|||
90
src/UserModule.cc
Normal file
90
src/UserModule.cc
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* OpenSCAD (www.openscad.org)
|
||||
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
|
||||
* Marius Kintel <marius@kintel.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* As a special exception, you have permission to link this program
|
||||
* with the CGAL library and distribute executables, as long as you
|
||||
* follow the requirements of the GNU GPL in regard to all of the
|
||||
* software in the executable aside from CGAL.
|
||||
*
|
||||
* 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 "UserModule.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "node.h"
|
||||
#include "evalcontext.h"
|
||||
#include "exceptions.h"
|
||||
#include "stackcheck.h"
|
||||
#include "modcontext.h"
|
||||
#include "expression.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
std::deque<std::string> UserModule::module_stack;
|
||||
|
||||
AbstractNode *UserModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||
{
|
||||
if (StackCheck::inst()->check()) {
|
||||
throw RecursionException::create("module", inst->name());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// At this point we know that nobody will modify the dependencies of the local scope
|
||||
// passed to this instance, so we can populate the context
|
||||
inst->scope.apply(*evalctx);
|
||||
|
||||
ModuleContext c(ctx, evalctx);
|
||||
// set $children first since we might have variables depending on it
|
||||
c.set_variable("$children", ValuePtr(double(inst->scope.children.size())));
|
||||
module_stack.push_back(inst->name());
|
||||
c.set_variable("$parent_modules", ValuePtr(double(module_stack.size())));
|
||||
c.initializeModule(*this);
|
||||
// FIXME: Set document path to the path of the module
|
||||
#if 0 && DEBUG
|
||||
c.dump(this, inst);
|
||||
#endif
|
||||
|
||||
AbstractNode *node = new GroupNode(inst);
|
||||
std::vector<AbstractNode *> instantiatednodes = this->scope.instantiateChildren(&c);
|
||||
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
||||
module_stack.pop_back();
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
std::string UserModule::dump(const std::string &indent, const std::string &name) const
|
||||
{
|
||||
std::stringstream dump;
|
||||
std::string tab;
|
||||
if (!name.empty()) {
|
||||
dump << indent << "module " << name << "(";
|
||||
for (size_t i=0; i < this->definition_arguments.size(); i++) {
|
||||
const Assignment &arg = this->definition_arguments[i];
|
||||
if (i > 0) dump << ", ";
|
||||
dump << arg.name;
|
||||
if (arg.expr) dump << " = " << *arg.expr;
|
||||
}
|
||||
dump << ") {\n";
|
||||
tab = "\t";
|
||||
}
|
||||
dump << scope.dump(indent + tab);
|
||||
if (!name.empty()) {
|
||||
dump << indent << "}\n";
|
||||
}
|
||||
return dump.str();
|
||||
}
|
||||
27
src/UserModule.h
Normal file
27
src/UserModule.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <deque>
|
||||
|
||||
#include "module.h"
|
||||
#include "localscope.h"
|
||||
|
||||
class UserModule : public AbstractModule, public ASTNode
|
||||
{
|
||||
public:
|
||||
UserModule(const Location &loc) : ASTNode(loc) { }
|
||||
UserModule(const class Feature& feature, const Location &loc) : AbstractModule(feature), ASTNode(loc) { }
|
||||
virtual ~UserModule() {}
|
||||
|
||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx = NULL) const;
|
||||
virtual std::string dump(const std::string &indent, const std::string &name) const;
|
||||
static const std::string& stack_element(int n) { return module_stack[n]; };
|
||||
static int stack_size() { return module_stack.size(); };
|
||||
|
||||
AssignmentList definition_arguments;
|
||||
|
||||
LocalScope scope;
|
||||
|
||||
private:
|
||||
static std::deque<std::string> module_stack;
|
||||
};
|
||||
|
|
@ -25,12 +25,13 @@
|
|||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "typedefs.h"
|
||||
#include"Assignment.h"
|
||||
#include "expression.h"
|
||||
#include "context.h"
|
||||
#include "evalcontext.h"
|
||||
#include <iostream>
|
||||
#include <boost/assign/std/vector.hpp>
|
||||
|
||||
using namespace boost::assign; // bring 'operator+=()' into scope
|
||||
|
||||
Annotation::Annotation(const std::string name, const AssignmentList assignments, const AssignmentList args)
|
||||
|
|
@ -82,6 +83,6 @@ void Annotation::dump()
|
|||
std::cout << " ANNOTATION: '" << name << "'" << std::endl;
|
||||
for (AssignmentList::const_iterator it = assignments.begin();it != assignments.end();it++) {
|
||||
const Assignment &assignment = (*it);
|
||||
std::cout << (*it).first << assignment.second << std::endl;
|
||||
std::cout << (*it).name << assignment.expr << std::endl;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,23 +24,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "Assignment.h"
|
||||
|
||||
Assignment::Assignment(std::string name)
|
||||
{
|
||||
first = name;
|
||||
second = shared_ptr<class Expression>();
|
||||
}
|
||||
|
||||
Assignment::Assignment(std::string name, shared_ptr<class Expression> expr)
|
||||
{
|
||||
first = name;
|
||||
second = expr;
|
||||
}
|
||||
|
||||
Assignment::~Assignment()
|
||||
{
|
||||
}
|
||||
|
||||
void Assignment::add_annotations(AnnotationList *annotations)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -94,19 +94,19 @@ std::string Builtins::isDeprecated(const std::string &name)
|
|||
|
||||
Builtins::Builtins()
|
||||
{
|
||||
this->globalscope.assignments.push_back(Assignment("$fn", shared_ptr<Expression>(new ExpressionConst(ValuePtr(0.0)))));
|
||||
this->globalscope.assignments.push_back(Assignment("$fs", shared_ptr<Expression>(new ExpressionConst(ValuePtr(2.0)))));
|
||||
this->globalscope.assignments.push_back(Assignment("$fa", shared_ptr<Expression>(new ExpressionConst(ValuePtr(12.0)))));
|
||||
this->globalscope.assignments.push_back(Assignment("$t", shared_ptr<Expression>(new ExpressionConst(ValuePtr(0.0)))));
|
||||
this->globalscope.assignments.push_back(Assignment("$fn", shared_ptr<Expression>(new Literal(ValuePtr(0.0)))));
|
||||
this->globalscope.assignments.push_back(Assignment("$fs", shared_ptr<Expression>(new Literal(ValuePtr(2.0)))));
|
||||
this->globalscope.assignments.push_back(Assignment("$fa", shared_ptr<Expression>(new Literal(ValuePtr(12.0)))));
|
||||
this->globalscope.assignments.push_back(Assignment("$t", shared_ptr<Expression>(new Literal(ValuePtr(0.0)))));
|
||||
|
||||
Value::VectorType zero3;
|
||||
zero3.push_back(ValuePtr(0.0));
|
||||
zero3.push_back(ValuePtr(0.0));
|
||||
zero3.push_back(ValuePtr(0.0));
|
||||
ValuePtr zero3val(zero3);
|
||||
this->globalscope.assignments.push_back(Assignment("$vpt", shared_ptr<Expression>(new ExpressionConst(zero3val))));
|
||||
this->globalscope.assignments.push_back(Assignment("$vpr", shared_ptr<Expression>(new ExpressionConst(zero3val))));
|
||||
this->globalscope.assignments.push_back(Assignment("$vpd", shared_ptr<Expression>(new ExpressionConst(ValuePtr(500)))));
|
||||
this->globalscope.assignments.push_back(Assignment("$vpt", shared_ptr<Expression>(new Literal(zero3val))));
|
||||
this->globalscope.assignments.push_back(Assignment("$vpr", shared_ptr<Expression>(new Literal(zero3val))));
|
||||
this->globalscope.assignments.push_back(Assignment("$vpd", shared_ptr<Expression>(new Literal(ValuePtr(500)))));
|
||||
}
|
||||
|
||||
Builtins::~Builtins()
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "cgaladvnode.h"
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "evalcontext.h"
|
||||
#include "builtin.h"
|
||||
#include "polyset.h"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "node.h"
|
||||
#include "visitor.h"
|
||||
#include "value.h"
|
||||
#include "linalg.h"
|
||||
|
||||
|
|
@ -16,13 +15,11 @@ enum cgaladv_type_e {
|
|||
class CgaladvNode : public AbstractNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
CgaladvNode(const ModuleInstantiation *mi, cgaladv_type_e type) : AbstractNode(mi), type(type) {
|
||||
convexity = 1;
|
||||
}
|
||||
virtual ~CgaladvNode() { }
|
||||
virtual Response accept(class State &state, Visitor &visitor) const {
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
virtual std::string toString() const;
|
||||
virtual std::string name() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ namespace CGALUtils {
|
|||
PRINTDB("After hull valid: %d", r.is_valid());
|
||||
success = !createPolySetFromPolyhedron(r, result);
|
||||
}
|
||||
catch (const CGAL::Assertion_exception &e) {
|
||||
catch (const CGAL::Failure_exception &e) {
|
||||
PRINTB("ERROR: CGAL error in applyHull(): %s", e.what());
|
||||
}
|
||||
CGAL::set_error_behaviour(old_behaviour);
|
||||
|
|
@ -207,6 +207,7 @@ namespace CGALUtils {
|
|||
*/
|
||||
Geometry const * applyMinkowski(const Geometry::Geometries &children)
|
||||
{
|
||||
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
|
||||
CGAL::Timer t,t_tot;
|
||||
assert(children.size() >= 2);
|
||||
Geometry::Geometries::const_iterator it = children.begin();
|
||||
|
|
@ -397,6 +398,7 @@ namespace CGALUtils {
|
|||
t_tot.stop();
|
||||
PRINTDB("Minkowski: Total execution time %f s", t_tot.time());
|
||||
t_tot.reset();
|
||||
CGAL::set_error_behaviour(old_behaviour);
|
||||
return operands[0];
|
||||
}
|
||||
catch (...) {
|
||||
|
|
@ -404,6 +406,7 @@ namespace CGALUtils {
|
|||
PRINTD("Minkowski: Falling back to Nef Minkowski");
|
||||
|
||||
CGAL_Nef_polyhedron *N = applyOperator(children, OPENSCAD_MINKOWSKI);
|
||||
CGAL::set_error_behaviour(old_behaviour);
|
||||
return N;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "colornode.h"
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "evalcontext.h"
|
||||
#include "builtin.h"
|
||||
#include "printutils.h"
|
||||
|
|
|
|||
|
|
@ -1,16 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "node.h"
|
||||
#include "visitor.h"
|
||||
#include "linalg.h"
|
||||
|
||||
class ColorNode : public AbstractNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
ColorNode(const ModuleInstantiation *mi) : AbstractNode(mi) { }
|
||||
virtual Response accept(class State &state, Visitor &visitor) const {
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
virtual std::string toString() const;
|
||||
virtual std::string name() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
%{
|
||||
#include "typedefs.h"
|
||||
#include "Assignment.h"
|
||||
#include "expression.h"
|
||||
#include "value.h"
|
||||
#include "comment_parser.h"
|
||||
|
|
@ -29,10 +29,12 @@ H [0-9a-fA-F]
|
|||
"]" { return yytext[0];}
|
||||
"," { return yytext[0];}
|
||||
":" { return yytext[0];}
|
||||
|
||||
[ \t]
|
||||
|
||||
[^(\[ \] \, \:)]* { yylval.text=strdup(yytext); return WORD;}
|
||||
|
||||
[\n\r ]
|
||||
[ \n\r ]
|
||||
|
||||
. { }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
#include<iostream>
|
||||
#include<string.h>
|
||||
using namespace std;
|
||||
#include "typedefs.h"
|
||||
#include "module.h"
|
||||
#include "Assignment.h"
|
||||
#include "expression.h"
|
||||
#include "value.h"
|
||||
void yyerror(char *);
|
||||
|
|
@ -16,6 +15,7 @@
|
|||
char ch;
|
||||
double num;
|
||||
class Expression *expr;
|
||||
class Vector *vec;
|
||||
Assignment *arg;
|
||||
AssignmentList *args;
|
||||
|
||||
|
|
@ -29,7 +29,8 @@
|
|||
%type <expr> expr
|
||||
%type <args> arguments_call
|
||||
%type <arg> argument_call
|
||||
%type <expr> vector_expr
|
||||
%type <vec> vector_expr
|
||||
%type <vec> labled_vector
|
||||
|
||||
%%
|
||||
|
||||
|
|
@ -59,17 +60,17 @@ argument_call:
|
|||
expr :
|
||||
NUM
|
||||
{
|
||||
$$ = new ExpressionConst(ValuePtr($1));
|
||||
$$ = new Literal(ValuePtr($1));
|
||||
|
||||
}
|
||||
| word
|
||||
{
|
||||
$$ = new ExpressionConst(ValuePtr(std::string($1)));
|
||||
$$ = new Literal(ValuePtr(std::string($1)));
|
||||
free($1);
|
||||
}
|
||||
| '[' optional_commas ']'
|
||||
{
|
||||
$$ = new ExpressionConst(ValuePtr(Value::VectorType()));
|
||||
$$ = new Literal(ValuePtr(Value::VectorType()));
|
||||
}
|
||||
| '[' vector_expr optional_commas ']'
|
||||
{
|
||||
|
|
@ -77,17 +78,21 @@ expr :
|
|||
}
|
||||
| '[' expr ':' expr ']'
|
||||
{
|
||||
$$ = new ExpressionRange($2, $4);
|
||||
$$ = new Range($2, $4,Location::NONE);
|
||||
}
|
||||
| '[' expr ':' expr ':' expr ']'
|
||||
{
|
||||
$$ = new ExpressionRange($2, $4, $6);
|
||||
}
|
||||
| expr ':' expr
|
||||
{
|
||||
$$ = new ExpressionVector($1);
|
||||
$$->children.push_back($3);
|
||||
$$ = new Range($2, $4, $6,Location::NONE);
|
||||
}
|
||||
| labled_vector { $$=$1;}
|
||||
;
|
||||
|
||||
labled_vector:
|
||||
expr ':' expr {
|
||||
$$ = new Vector(Location::NONE);
|
||||
$$->push_back($1);
|
||||
$$->push_back($3);
|
||||
}
|
||||
;
|
||||
|
||||
optional_commas:
|
||||
|
|
@ -98,12 +103,13 @@ optional_commas:
|
|||
vector_expr:
|
||||
expr
|
||||
{
|
||||
$$ = new ExpressionVector($1);
|
||||
$$ = new Vector(Location::NONE);
|
||||
$$->push_back($1);
|
||||
}
|
||||
| vector_expr ',' optional_commas expr
|
||||
{
|
||||
$$ = $1;
|
||||
$$->children.push_back($4);
|
||||
$$->push_back($4);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -124,12 +130,14 @@ word:
|
|||
|
||||
void yyerror(char *msg) {
|
||||
cout<<msg<<endl;
|
||||
argument=NULL;
|
||||
}
|
||||
|
||||
AssignmentList * parser(const char *text) {
|
||||
|
||||
yy_scan_string(text);
|
||||
int parserretval = yyparse();
|
||||
if (parserretval != 0) return NULL;
|
||||
return argument;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@
|
|||
#include "evalcontext.h"
|
||||
#include "expression.h"
|
||||
#include "function.h"
|
||||
#include "module.h"
|
||||
#include "UserModule.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "builtin.h"
|
||||
#include "printutils.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
|
|
@ -77,7 +78,7 @@ void Context::setVariables(const AssignmentList &args,
|
|||
const EvalContext *evalctx)
|
||||
{
|
||||
for(const auto &arg : args) {
|
||||
set_variable(arg.first, arg.second ? arg.second->evaluate(this->parent) : ValuePtr::undefined);
|
||||
set_variable(arg.name, arg.expr ? arg.expr->evaluate(this->parent) : ValuePtr::undefined);
|
||||
}
|
||||
|
||||
if (evalctx) {
|
||||
|
|
@ -86,7 +87,7 @@ void Context::setVariables(const AssignmentList &args,
|
|||
const std::string &name = evalctx->getArgName(i);
|
||||
ValuePtr val = evalctx->getArgValue(i);
|
||||
if (name.empty()) {
|
||||
if (posarg < args.size()) this->set_variable(args[posarg++].first, val);
|
||||
if (posarg < args.size()) this->set_variable(args[posarg++].name, val);
|
||||
} else {
|
||||
this->set_variable(name, val);
|
||||
}
|
||||
|
|
@ -211,11 +212,11 @@ std::string Context::dump(const AbstractModule *mod, const ModuleInstantiation *
|
|||
s << boost::format("Context: %p (%p)") % this % this->parent;
|
||||
s << boost::format(" document path: %s") % this->document_path;
|
||||
if (mod) {
|
||||
const Module *m = dynamic_cast<const Module*>(mod);
|
||||
const UserModule *m = dynamic_cast<const UserModule*>(mod);
|
||||
if (m) {
|
||||
s << " module args:";
|
||||
for(const auto &arg : m->definition_arguments) {
|
||||
s << boost::format(" %s = %s") % arg.first % variables[arg.first];
|
||||
s << boost::format(" %s = %s") % arg.name % variables[arg.name];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include "value.h"
|
||||
#include "typedefs.h"
|
||||
#include "Assignment.h"
|
||||
#include "memory.h"
|
||||
|
||||
class Context
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "node.h"
|
||||
#include "evalcontext.h"
|
||||
#include "modcontext.h"
|
||||
|
|
@ -100,7 +101,7 @@ void ControlModule::for_eval(AbstractNode &node, const ModuleInstantiation &inst
|
|||
// the local scope (as they may depend on the for loop variables
|
||||
Context c(ctx);
|
||||
for(const auto &ass : inst.scope.assignments) {
|
||||
c.set_variable(ass.first, ass.second->evaluate(&c));
|
||||
c.set_variable(ass.name, ass.expr->evaluate(&c));
|
||||
}
|
||||
|
||||
std::vector<AbstractNode *> instantiatednodes = inst.instantiateChildren(&c);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "evalcontext.h"
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "csgnode.h"
|
||||
#include "builtin.h"
|
||||
#include <sstream>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "node.h"
|
||||
#include "visitor.h"
|
||||
#include "enums.h"
|
||||
|
||||
class CsgOpNode : public AbstractNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
OpenSCADOperator type;
|
||||
CsgOpNode(const ModuleInstantiation *mi, OpenSCADOperator type) : AbstractNode(mi), type(type) { }
|
||||
virtual Response accept(class State &state, Visitor &visitor) const {
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
virtual std::string toString() const;
|
||||
virtual std::string name() const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "evalcontext.h"
|
||||
#include "module.h"
|
||||
#include "UserModule.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "expression.h"
|
||||
#include "function.h"
|
||||
#include "printutils.h"
|
||||
|
|
@ -16,7 +17,7 @@ EvalContext::EvalContext(const Context *parent,
|
|||
const std::string &EvalContext::getArgName(size_t i) const
|
||||
{
|
||||
assert(i < this->eval_arguments.size());
|
||||
return this->eval_arguments[i].first;
|
||||
return this->eval_arguments[i].name;
|
||||
}
|
||||
|
||||
ValuePtr EvalContext::getArgValue(size_t i, const Context *ctx) const
|
||||
|
|
@ -24,8 +25,8 @@ ValuePtr EvalContext::getArgValue(size_t i, const Context *ctx) const
|
|||
assert(i < this->eval_arguments.size());
|
||||
const Assignment &arg = this->eval_arguments[i];
|
||||
ValuePtr v;
|
||||
if (arg.second) {
|
||||
v = arg.second->evaluate(ctx ? ctx : this);
|
||||
if (arg.expr) {
|
||||
v = arg.expr->evaluate(ctx ? ctx : this);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
|
@ -44,11 +45,11 @@ void EvalContext::assignTo(Context &target) const
|
|||
{
|
||||
for(const auto &assignment : this->eval_arguments) {
|
||||
ValuePtr v;
|
||||
if (assignment.second) v = assignment.second->evaluate(&target);
|
||||
if (target.has_local_variable(assignment.first)) {
|
||||
PRINTB("WARNING: Ignoring duplicate variable assignment %s = %s", assignment.first % v->toString());
|
||||
if (assignment.expr) v = assignment.expr->evaluate(&target);
|
||||
if (target.has_local_variable(assignment.name)) {
|
||||
PRINTB("WARNING: Ignoring duplicate variable assignment %s = %s", assignment.name % v->toString());
|
||||
} else {
|
||||
target.set_variable(assignment.first, v);
|
||||
target.set_variable(assignment.name, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -65,7 +66,7 @@ std::string EvalContext::dump(const AbstractModule *mod, const ModuleInstantiati
|
|||
|
||||
s << boost::format(" eval args:");
|
||||
for (size_t i=0;i<this->eval_arguments.size();i++) {
|
||||
s << boost::format(" %s = %s") % this->eval_arguments[i].first % this->eval_arguments[i].second;
|
||||
s << boost::format(" %s = %s") % this->eval_arguments[i].name % this->eval_arguments[i].expr;
|
||||
}
|
||||
if (this->scope && this->scope->children.size() > 0) {
|
||||
s << boost::format(" children:");
|
||||
|
|
@ -74,11 +75,11 @@ std::string EvalContext::dump(const AbstractModule *mod, const ModuleInstantiati
|
|||
}
|
||||
}
|
||||
if (mod) {
|
||||
const Module *m = dynamic_cast<const Module*>(mod);
|
||||
const UserModule *m = dynamic_cast<const UserModule*>(mod);
|
||||
if (m) {
|
||||
s << boost::format(" module args:");
|
||||
for(const auto &arg : m->definition_arguments) {
|
||||
s << boost::format(" %s = %s") % arg.first % *(variables[arg.first]);
|
||||
s << boost::format(" %s = %s") % arg.name % *(variables[arg.name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "context.h"
|
||||
#include "Assignment.h"
|
||||
|
||||
/*!
|
||||
This hold the evaluation context (the parameters actually sent
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
|
||||
class EvaluationException : public std::runtime_error {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@ void export_png(const shared_ptr<const class CGAL_Nef_polyhedron> &root_N, Camer
|
|||
void export_png_with_opencsg(Tree &tree, Camera &c, std::ostream &output);
|
||||
void export_png_with_throwntogether(Tree &tree, Camera &c, std::ostream &output);
|
||||
|
||||
void export_parameter(std::ostream &output, FileModule *fileModule);
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void export_stl(const class PolySet &ps, std::ostream &output);
|
||||
|
|
|
|||
580
src/expr.cc
580
src/expr.cc
|
|
@ -30,7 +30,6 @@
|
|||
#include <assert.h>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include "stl-utils.h"
|
||||
#include "printutils.h"
|
||||
#include "stackcheck.h"
|
||||
#include "exceptions.h"
|
||||
|
|
@ -58,42 +57,14 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
Expression::Expression() : first(NULL), second(NULL), third(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
Expression::Expression(Expression *expr) : first(expr), second(NULL), third(NULL)
|
||||
{
|
||||
children.push_back(expr);
|
||||
}
|
||||
|
||||
Expression::Expression(Expression *left, Expression *right) : first(left), second(right), third(NULL)
|
||||
{
|
||||
children.push_back(left);
|
||||
children.push_back(right);
|
||||
}
|
||||
|
||||
Expression::Expression(Expression *expr1, Expression *expr2, Expression *expr3)
|
||||
: first(expr1), second(expr2), third(expr3)
|
||||
{
|
||||
children.push_back(expr1);
|
||||
children.push_back(expr2);
|
||||
children.push_back(expr3);
|
||||
}
|
||||
|
||||
Expression::~Expression()
|
||||
{
|
||||
std::for_each(this->children.begin(), this->children.end(), del_fun<Expression>());
|
||||
}
|
||||
|
||||
namespace /* anonymous*/ {
|
||||
|
||||
std::ostream &operator << (std::ostream &o, AssignmentList const& l) {
|
||||
for (size_t i=0; i < l.size(); i++) {
|
||||
const Assignment &arg = l[i];
|
||||
if (i > 0) o << ", ";
|
||||
if (!arg.first.empty()) o << arg.first << " = ";
|
||||
o << *arg.second;
|
||||
if (!arg.name.empty()) o << arg.name << " = ";
|
||||
o << *arg.expr;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
|
@ -105,278 +76,215 @@ bool Expression::isListComprehension() const
|
|||
return false;
|
||||
}
|
||||
|
||||
ExpressionNot::ExpressionNot(Expression *expr) : Expression(expr)
|
||||
UnaryOp::UnaryOp(UnaryOp::Op op, Expression *expr, const Location &loc) : Expression(loc), op(op), expr(expr)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionNot::evaluate(const Context *context) const
|
||||
ValuePtr UnaryOp::evaluate(const Context *context) const
|
||||
{
|
||||
return !first->evaluate(context);
|
||||
switch (this->op) {
|
||||
case (Op::Not):
|
||||
return !this->expr->evaluate(context);
|
||||
case (Op::Negate):
|
||||
return -this->expr->evaluate(context);
|
||||
default:
|
||||
break;
|
||||
// FIXME: error:
|
||||
}
|
||||
}
|
||||
|
||||
void ExpressionNot::print(std::ostream &stream) const
|
||||
const char *UnaryOp::opString() const
|
||||
{
|
||||
stream << "!" << *first;
|
||||
switch (this->op) {
|
||||
case Op::Not:
|
||||
return "!";
|
||||
break;
|
||||
case Op::Negate:
|
||||
return "-";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
// FIXME: Error: unknown op
|
||||
}
|
||||
}
|
||||
|
||||
ExpressionLogicalAnd::ExpressionLogicalAnd(Expression *left, Expression *right) : Expression(left, right)
|
||||
void UnaryOp::print(std::ostream &stream) const
|
||||
{
|
||||
stream << opString() << *this->expr;
|
||||
}
|
||||
|
||||
BinaryOp::BinaryOp(Expression *left, BinaryOp::Op op, Expression *right, const Location &loc) :
|
||||
Expression(loc), op(op), left(left), right(right)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionLogicalAnd::evaluate(const Context *context) const
|
||||
ValuePtr BinaryOp::evaluate(const Context *context) const
|
||||
{
|
||||
return this->first->evaluate(context) && this->second->evaluate(context);
|
||||
switch (this->op) {
|
||||
case Op::LogicalAnd:
|
||||
return this->left->evaluate(context) && this->right->evaluate(context);
|
||||
break;
|
||||
case Op::LogicalOr:
|
||||
return this->left->evaluate(context) || this->right->evaluate(context);
|
||||
break;
|
||||
case Op::Multiply:
|
||||
return this->left->evaluate(context) * this->right->evaluate(context);
|
||||
break;
|
||||
case Op::Divide:
|
||||
return this->left->evaluate(context) / this->right->evaluate(context);
|
||||
break;
|
||||
case Op::Modulo:
|
||||
return this->left->evaluate(context) % this->right->evaluate(context);
|
||||
break;
|
||||
case Op::Plus:
|
||||
return this->left->evaluate(context) + this->right->evaluate(context);
|
||||
break;
|
||||
case Op::Minus:
|
||||
return this->left->evaluate(context) - this->right->evaluate(context);
|
||||
break;
|
||||
case Op::Less:
|
||||
return this->left->evaluate(context) < this->right->evaluate(context);
|
||||
break;
|
||||
case Op::LessEqual:
|
||||
return this->left->evaluate(context) <= this->right->evaluate(context);
|
||||
break;
|
||||
case Op::Greater:
|
||||
return this->left->evaluate(context) > this->right->evaluate(context);
|
||||
break;
|
||||
case Op::GreaterEqual:
|
||||
return this->left->evaluate(context) >= this->right->evaluate(context);
|
||||
break;
|
||||
case Op::Equal:
|
||||
return this->left->evaluate(context) == this->right->evaluate(context);
|
||||
break;
|
||||
case Op::NotEqual:
|
||||
return this->left->evaluate(context) != this->right->evaluate(context);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
// FIXME: Error: unknown op
|
||||
}
|
||||
}
|
||||
|
||||
void ExpressionLogicalAnd::print(std::ostream &stream) const
|
||||
const char *BinaryOp::opString() const
|
||||
{
|
||||
stream << "(" << *first << " && " << *second << ")";
|
||||
switch (this->op) {
|
||||
case Op::LogicalAnd:
|
||||
return "&&";
|
||||
break;
|
||||
case Op::LogicalOr:
|
||||
return "||";
|
||||
break;
|
||||
case Op::Multiply:
|
||||
return "*";
|
||||
break;
|
||||
case Op::Divide:
|
||||
return "/";
|
||||
break;
|
||||
case Op::Modulo:
|
||||
return "%";
|
||||
break;
|
||||
case Op::Plus:
|
||||
return "+";
|
||||
break;
|
||||
case Op::Minus:
|
||||
return "-";
|
||||
break;
|
||||
case Op::Less:
|
||||
return "<";
|
||||
break;
|
||||
case Op::LessEqual:
|
||||
return "<=";
|
||||
break;
|
||||
case Op::Greater:
|
||||
return ">";
|
||||
break;
|
||||
case Op::GreaterEqual:
|
||||
return ">=";
|
||||
break;
|
||||
case Op::Equal:
|
||||
return "==";
|
||||
break;
|
||||
case Op::NotEqual:
|
||||
return "!=";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
// FIXME: Error: unknown op
|
||||
}
|
||||
}
|
||||
|
||||
ExpressionLogicalOr::ExpressionLogicalOr(Expression *left, Expression *right) : Expression(left, right)
|
||||
void BinaryOp::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "(" << *this->left << " " << opString() << " " << *this->right << ")";
|
||||
}
|
||||
|
||||
TernaryOp::TernaryOp(Expression *cond, Expression *ifexpr, Expression *elseexpr, const Location &loc)
|
||||
: Expression(loc), cond(cond), ifexpr(ifexpr), elseexpr(elseexpr)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionLogicalOr::evaluate(const Context *context) const
|
||||
ValuePtr TernaryOp::evaluate(const Context *context) const
|
||||
{
|
||||
return this->first->evaluate(context) || this->second->evaluate(context);
|
||||
return (this->cond->evaluate(context) ? this->ifexpr : this->elseexpr)->evaluate(context);
|
||||
}
|
||||
|
||||
void ExpressionLogicalOr::print(std::ostream &stream) const
|
||||
void TernaryOp::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "(" << *first << " || " << *second << ")";
|
||||
stream << "(" << *this->cond << " ? " << *this->ifexpr << " : " << *this->elseexpr << ")";
|
||||
}
|
||||
|
||||
ExpressionMultiply::ExpressionMultiply(Expression *left, Expression *right) : Expression(left, right)
|
||||
ArrayLookup::ArrayLookup(Expression *array, Expression *index, const Location &loc)
|
||||
: Expression(loc), array(array), index(index)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionMultiply::evaluate(const Context *context) const
|
||||
{
|
||||
return this->first->evaluate(context) * this->second->evaluate(context);
|
||||
ValuePtr ArrayLookup::evaluate(const Context *context) const {
|
||||
return this->array->evaluate(context)[this->index->evaluate(context)];
|
||||
}
|
||||
|
||||
void ExpressionMultiply::print(std::ostream &stream) const
|
||||
void ArrayLookup::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "(" << *first << " * " << *second << ")";
|
||||
stream << *array << "[" << *index << "]";
|
||||
}
|
||||
|
||||
ExpressionDivision::ExpressionDivision(Expression *left, Expression *right) : Expression(left, right)
|
||||
Literal::Literal(const ValuePtr &val, const Location &loc) : Expression(loc), value(val)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionDivision::evaluate(const Context *context) const
|
||||
ValuePtr Literal::evaluate(const class Context *) const
|
||||
{
|
||||
return this->first->evaluate(context) / this->second->evaluate(context);
|
||||
return this->value;
|
||||
}
|
||||
|
||||
void ExpressionDivision::print(std::ostream &stream) const
|
||||
void Literal::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "(" << *first << " / " << *second << ")";
|
||||
stream << *this->value;
|
||||
}
|
||||
|
||||
ExpressionModulo::ExpressionModulo(Expression *left, Expression *right) : Expression(left, right)
|
||||
Range::Range(Expression *begin, Expression *end, const Location &loc)
|
||||
: Expression(loc), begin(begin), end(end)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionModulo::evaluate(const Context *context) const
|
||||
{
|
||||
return this->first->evaluate(context) % this->second->evaluate(context);
|
||||
}
|
||||
|
||||
void ExpressionModulo::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "(" << *first << " % " << *second << ")";
|
||||
}
|
||||
|
||||
ExpressionPlus::ExpressionPlus(Expression *left, Expression *right) : Expression(left, right)
|
||||
Range::Range(Expression *begin, Expression *step, Expression *end, const Location &loc)
|
||||
: Expression(loc), begin(begin), step(step), end(end)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionPlus::evaluate(const Context *context) const
|
||||
ValuePtr Range::evaluate(const Context *context) const
|
||||
{
|
||||
return this->first->evaluate(context) + this->second->evaluate(context);
|
||||
}
|
||||
|
||||
void ExpressionPlus::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "(" << *first << " + " << *second << ")";
|
||||
}
|
||||
|
||||
ExpressionMinus::ExpressionMinus(Expression *left, Expression *right) : Expression(left, right)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionMinus::evaluate(const Context *context) const
|
||||
{
|
||||
return this->first->evaluate(context) - this->second->evaluate(context);
|
||||
}
|
||||
|
||||
void ExpressionMinus::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "(" << *first << " - " << *second << ")";
|
||||
}
|
||||
|
||||
ExpressionLess::ExpressionLess(Expression *left, Expression *right) : Expression(left, right)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionLess::evaluate(const Context *context) const
|
||||
{
|
||||
return this->first->evaluate(context) < this->second->evaluate(context);
|
||||
}
|
||||
|
||||
void ExpressionLess::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "(" << *first << " < " << *second << ")";
|
||||
}
|
||||
|
||||
ExpressionLessOrEqual::ExpressionLessOrEqual(Expression *left, Expression *right) : Expression(left, right)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionLessOrEqual::evaluate(const Context *context) const
|
||||
{
|
||||
return this->first->evaluate(context) <= this->second->evaluate(context);
|
||||
}
|
||||
|
||||
void ExpressionLessOrEqual::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "(" << *first << " <= " << *second << ")";
|
||||
}
|
||||
|
||||
ExpressionEqual::ExpressionEqual(Expression *left, Expression *right) : Expression(left, right)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionEqual::evaluate(const Context *context) const
|
||||
{
|
||||
return this->first->evaluate(context) == this->second->evaluate(context);
|
||||
}
|
||||
|
||||
void ExpressionEqual::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "(" << *first << " == " << *second << ")";
|
||||
}
|
||||
|
||||
ExpressionNotEqual::ExpressionNotEqual(Expression *left, Expression *right) : Expression(left, right)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionNotEqual::evaluate(const Context *context) const
|
||||
{
|
||||
return this->first->evaluate(context) != this->second->evaluate(context);
|
||||
}
|
||||
|
||||
void ExpressionNotEqual::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "(" << *first << " != " << *second << ")";
|
||||
}
|
||||
|
||||
ExpressionGreaterOrEqual::ExpressionGreaterOrEqual(Expression *left, Expression *right) : Expression(left, right)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionGreaterOrEqual::evaluate(const Context *context) const
|
||||
{
|
||||
return this->first->evaluate(context) >= this->second->evaluate(context);
|
||||
}
|
||||
|
||||
void ExpressionGreaterOrEqual::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "(" << *first << " >= " << *second << ")";
|
||||
}
|
||||
|
||||
ExpressionGreater::ExpressionGreater(Expression *left, Expression *right) : Expression(left, right)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionGreater::evaluate(const Context *context) const
|
||||
{
|
||||
return this->first->evaluate(context) > this->second->evaluate(context);
|
||||
}
|
||||
|
||||
void ExpressionGreater::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "(" << *first << " > " << *second << ")";
|
||||
}
|
||||
|
||||
ExpressionTernary::ExpressionTernary(Expression *expr1, Expression *expr2, Expression *expr3) : Expression(expr1, expr2, expr3)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionTernary::evaluate(const Context *context) const
|
||||
{
|
||||
return (this->first->evaluate(context) ? this->second : this->third)->evaluate(context);
|
||||
}
|
||||
|
||||
void ExpressionTernary::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "(" << *first << " ? " << *second << " : " << *third << ")";
|
||||
}
|
||||
|
||||
ExpressionArrayLookup::ExpressionArrayLookup(Expression *left, Expression *right) : Expression(left, right)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionArrayLookup::evaluate(const Context *context) const {
|
||||
return this->first->evaluate(context)[this->second->evaluate(context)];
|
||||
}
|
||||
|
||||
void ExpressionArrayLookup::print(std::ostream &stream) const
|
||||
{
|
||||
stream << *first << "[" << *second << "]";
|
||||
}
|
||||
|
||||
ExpressionInvert::ExpressionInvert(Expression *expr) : Expression(expr)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionInvert::evaluate(const Context *context) const
|
||||
{
|
||||
return -this->first->evaluate(context);
|
||||
}
|
||||
|
||||
void ExpressionInvert::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "-" << *first;
|
||||
}
|
||||
|
||||
ExpressionConst::ExpressionConst(const ValuePtr &val) : const_value(val)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionConst::evaluate(const class Context *) const
|
||||
{
|
||||
return this->const_value;
|
||||
}
|
||||
|
||||
void ExpressionConst::print(std::ostream &stream) const
|
||||
{
|
||||
stream << *this->const_value;
|
||||
}
|
||||
|
||||
ExpressionRange::ExpressionRange(Expression *expr1, Expression *expr2) : Expression(expr1, expr2)
|
||||
{
|
||||
}
|
||||
|
||||
ExpressionRange::ExpressionRange(Expression *expr1, Expression *expr2, Expression *expr3) : Expression(expr1, expr2, expr3)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionRange::evaluate(const Context *context) const
|
||||
{
|
||||
ValuePtr v1 = this->first->evaluate(context);
|
||||
if (v1->type() == Value::NUMBER) {
|
||||
ValuePtr v2 = this->second->evaluate(context);
|
||||
if (v2->type() == Value::NUMBER) {
|
||||
if (this->children.size() == 2) {
|
||||
RangeType range(v1->toDouble(), v2->toDouble());
|
||||
ValuePtr beginValue = this->begin->evaluate(context);
|
||||
if (beginValue->type() == Value::NUMBER) {
|
||||
ValuePtr endValue = this->end->evaluate(context);
|
||||
if (endValue->type() == Value::NUMBER) {
|
||||
if (!this->step) {
|
||||
RangeType range(beginValue->toDouble(), endValue->toDouble());
|
||||
return ValuePtr(range);
|
||||
} else {
|
||||
ValuePtr v3 = this->third->evaluate(context);
|
||||
if (v3->type() == Value::NUMBER) {
|
||||
RangeType range(v1->toDouble(), v2->toDouble(), v3->toDouble());
|
||||
ValuePtr stepValue = this->step->evaluate(context);
|
||||
if (stepValue->type() == Value::NUMBER) {
|
||||
RangeType range(beginValue->toDouble(), stepValue->toDouble(), endValue->toDouble());
|
||||
return ValuePtr(range);
|
||||
}
|
||||
}
|
||||
|
|
@ -385,18 +293,24 @@ ValuePtr ExpressionRange::evaluate(const Context *context) const
|
|||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
void ExpressionRange::print(std::ostream &stream) const
|
||||
void Range::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "[" << *first << " : " << *second;
|
||||
if (this->children.size() > 2) stream << " : " << *third;
|
||||
stream << "[" << *this->begin;
|
||||
if (this->step) stream << " : " << *this->step;
|
||||
stream << " : " << *this->end;
|
||||
stream << "]";
|
||||
}
|
||||
|
||||
ExpressionVector::ExpressionVector(Expression *expr) : Expression(expr)
|
||||
Vector::Vector(const Location &loc) : Expression(loc)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionVector::evaluate(const Context *context) const
|
||||
void Vector::push_back(Expression *expr)
|
||||
{
|
||||
this->children.push_back(shared_ptr<Expression>(expr));
|
||||
}
|
||||
|
||||
ValuePtr Vector::evaluate(const Context *context) const
|
||||
{
|
||||
Value::VectorType vec;
|
||||
for(const auto &e : this->children) {
|
||||
|
|
@ -413,7 +327,7 @@ ValuePtr ExpressionVector::evaluate(const Context *context) const
|
|||
return ValuePtr(vec);
|
||||
}
|
||||
|
||||
void ExpressionVector::print(std::ostream &stream) const
|
||||
void Vector::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "[";
|
||||
for (size_t i=0; i < this->children.size(); i++) {
|
||||
|
|
@ -423,28 +337,28 @@ void ExpressionVector::print(std::ostream &stream) const
|
|||
stream << "]";
|
||||
}
|
||||
|
||||
ExpressionLookup::ExpressionLookup(const std::string &var_name) : var_name(var_name)
|
||||
Lookup::Lookup(const std::string &name, const Location &loc) : Expression(loc), name(name)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionLookup::evaluate(const Context *context) const
|
||||
ValuePtr Lookup::evaluate(const Context *context) const
|
||||
{
|
||||
return context->lookup_variable(this->var_name);
|
||||
return context->lookup_variable(this->name);
|
||||
}
|
||||
|
||||
void ExpressionLookup::print(std::ostream &stream) const
|
||||
void Lookup::print(std::ostream &stream) const
|
||||
{
|
||||
stream << this->var_name;
|
||||
stream << this->name;
|
||||
}
|
||||
|
||||
ExpressionMember::ExpressionMember(Expression *expr, const std::string &member)
|
||||
: Expression(expr), member(member)
|
||||
MemberLookup::MemberLookup(Expression *expr, const std::string &member, const Location &loc)
|
||||
: Expression(loc), expr(expr), member(member)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionMember::evaluate(const Context *context) const
|
||||
ValuePtr MemberLookup::evaluate(const Context *context) const
|
||||
{
|
||||
ValuePtr v = this->first->evaluate(context);
|
||||
ValuePtr v = this->expr->evaluate(context);
|
||||
|
||||
if (v->type() == Value::VECTOR) {
|
||||
if (this->member == "x") return v[0];
|
||||
|
|
@ -458,80 +372,75 @@ ValuePtr ExpressionMember::evaluate(const Context *context) const
|
|||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
void ExpressionMember::print(std::ostream &stream) const
|
||||
void MemberLookup::print(std::ostream &stream) const
|
||||
{
|
||||
stream << *first << "." << this->member;
|
||||
stream << *this->expr << "." << this->member;
|
||||
}
|
||||
|
||||
ExpressionFunctionCall::ExpressionFunctionCall(const std::string &funcname,
|
||||
const AssignmentList &arglist)
|
||||
: funcname(funcname), call_arguments(arglist)
|
||||
FunctionCall::FunctionCall(const std::string &name,
|
||||
const AssignmentList &args, const Location &loc)
|
||||
: Expression(loc), name(name), arguments(args)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionFunctionCall::evaluate(const Context *context) const
|
||||
ValuePtr FunctionCall::evaluate(const Context *context) const
|
||||
{
|
||||
if (StackCheck::inst()->check()) {
|
||||
throw RecursionException::create("function", funcname);
|
||||
throw RecursionException::create("function", this->name);
|
||||
}
|
||||
|
||||
EvalContext c(context, this->call_arguments);
|
||||
ValuePtr result = context->evaluate_function(this->funcname, &c);
|
||||
EvalContext c(context, this->arguments);
|
||||
ValuePtr result = context->evaluate_function(this->name, &c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ExpressionFunctionCall::print(std::ostream &stream) const
|
||||
void FunctionCall::print(std::ostream &stream) const
|
||||
{
|
||||
stream << this->funcname << "(" << this->call_arguments << ")";
|
||||
stream << this->name << "(" << this->arguments << ")";
|
||||
}
|
||||
|
||||
ExpressionLet::ExpressionLet(const AssignmentList &arglist, Expression *expr)
|
||||
: Expression(expr), call_arguments(arglist)
|
||||
Let::Let(const AssignmentList &args, Expression *expr, const Location &loc)
|
||||
: Expression(loc), arguments(args), expr(expr)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionLet::evaluate(const Context *context) const
|
||||
ValuePtr Let::evaluate(const Context *context) const
|
||||
{
|
||||
Context c(context);
|
||||
evaluate_sequential_assignment(this->call_arguments, &c);
|
||||
evaluate_sequential_assignment(this->arguments, &c);
|
||||
|
||||
return this->first->evaluate(&c);
|
||||
return this->expr->evaluate(&c);
|
||||
}
|
||||
|
||||
void ExpressionLet::print(std::ostream &stream) const
|
||||
void Let::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "let(" << this->call_arguments << ") " << *first;
|
||||
stream << "let(" << this->arguments << ") " << *expr;
|
||||
}
|
||||
|
||||
ExpressionLc::ExpressionLc(Expression *expr) : Expression(expr)
|
||||
ListComprehension::ListComprehension(const Location &loc) : Expression(loc)
|
||||
{
|
||||
}
|
||||
|
||||
ExpressionLc::ExpressionLc(Expression *expr1, Expression *expr2)
|
||||
: Expression(expr1, expr2)
|
||||
{
|
||||
}
|
||||
|
||||
bool ExpressionLc::isListComprehension() const
|
||||
bool ListComprehension::isListComprehension() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
ExpressionLcIf::ExpressionLcIf(Expression *cond, Expression *exprIf, Expression *exprElse)
|
||||
: ExpressionLc(exprIf, exprElse), cond(cond)
|
||||
LcIf::LcIf(Expression *cond, Expression *ifexpr, Expression *elseexpr, const Location &loc)
|
||||
: ListComprehension(loc), cond(cond), ifexpr(ifexpr), elseexpr(elseexpr)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionLcIf::evaluate(const Context *context) const
|
||||
ValuePtr LcIf::evaluate(const Context *context) const
|
||||
{
|
||||
if (this->second) {
|
||||
if (this->elseexpr) {
|
||||
ExperimentalFeatureException::check(Feature::ExperimentalElseExpression);
|
||||
}
|
||||
|
||||
const Expression *expr = this->cond->evaluate(context) ? this->first : this->second;
|
||||
|
||||
Value::VectorType vec;
|
||||
const shared_ptr<Expression> &expr = this->cond->evaluate(context) ? this->ifexpr : this->elseexpr;
|
||||
|
||||
Value::VectorType vec;
|
||||
if (expr) {
|
||||
if (expr->isListComprehension()) {
|
||||
return expr->evaluate(context);
|
||||
|
|
@ -543,26 +452,25 @@ ValuePtr ExpressionLcIf::evaluate(const Context *context) const
|
|||
return ValuePtr(vec);
|
||||
}
|
||||
|
||||
void ExpressionLcIf::print(std::ostream &stream) const
|
||||
void LcIf::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "if(" << *this->cond << ") (" << *this->first << ")";
|
||||
if (this->second) {
|
||||
stream << " else (" << *this->second << ")";
|
||||
stream << "if(" << *this->cond << ") (" << *this->ifexpr << ")";
|
||||
if (this->elseexpr) {
|
||||
stream << " else (" << *this->elseexpr << ")";
|
||||
}
|
||||
}
|
||||
|
||||
ExpressionLcEach::ExpressionLcEach(Expression *expr)
|
||||
: ExpressionLc(expr)
|
||||
LcEach::LcEach(Expression *expr, const Location &loc) : ListComprehension(loc), expr(expr)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionLcEach::evaluate(const Context *context) const
|
||||
ValuePtr LcEach::evaluate(const Context *context) const
|
||||
{
|
||||
ExperimentalFeatureException::check(Feature::ExperimentalEachExpression);
|
||||
|
||||
Value::VectorType vec;
|
||||
|
||||
ValuePtr v = this->first->evaluate(context);
|
||||
ValuePtr v = this->expr->evaluate(context);
|
||||
|
||||
if (v->type() == Value::RANGE) {
|
||||
RangeType range = v->toRange();
|
||||
|
|
@ -583,28 +491,28 @@ ValuePtr ExpressionLcEach::evaluate(const Context *context) const
|
|||
vec.push_back(v);
|
||||
}
|
||||
|
||||
if (this->first->isListComprehension()) {
|
||||
if (this->expr->isListComprehension()) {
|
||||
return ValuePtr(flatten(vec));
|
||||
} else {
|
||||
return ValuePtr(vec);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpressionLcEach::print(std::ostream &stream) const
|
||||
void LcEach::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "each (" << *this->first << ")";
|
||||
stream << "each (" << *this->expr << ")";
|
||||
}
|
||||
|
||||
ExpressionLcFor::ExpressionLcFor(const AssignmentList &arglist, Expression *expr)
|
||||
: ExpressionLc(expr), call_arguments(arglist)
|
||||
LcFor::LcFor(const AssignmentList &args, Expression *expr, const Location &loc)
|
||||
: ListComprehension(loc), arguments(args), expr(expr)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionLcFor::evaluate(const Context *context) const
|
||||
ValuePtr LcFor::evaluate(const Context *context) const
|
||||
{
|
||||
Value::VectorType vec;
|
||||
|
||||
EvalContext for_context(context, this->call_arguments);
|
||||
EvalContext for_context(context, this->arguments);
|
||||
|
||||
Context assign_context(context);
|
||||
|
||||
|
|
@ -622,48 +530,48 @@ ValuePtr ExpressionLcFor::evaluate(const Context *context) const
|
|||
} else {
|
||||
for (RangeType::iterator it = range.begin();it != range.end();it++) {
|
||||
c.set_variable(it_name, ValuePtr(*it));
|
||||
vec.push_back(this->first->evaluate(&c));
|
||||
vec.push_back(this->expr->evaluate(&c));
|
||||
}
|
||||
}
|
||||
} else if (it_values->type() == Value::VECTOR) {
|
||||
for (size_t i = 0; i < it_values->toVector().size(); i++) {
|
||||
c.set_variable(it_name, it_values->toVector()[i]);
|
||||
vec.push_back(this->first->evaluate(&c));
|
||||
vec.push_back(this->expr->evaluate(&c));
|
||||
}
|
||||
} else if (it_values->type() != Value::UNDEFINED) {
|
||||
c.set_variable(it_name, it_values);
|
||||
vec.push_back(this->first->evaluate(&c));
|
||||
vec.push_back(this->expr->evaluate(&c));
|
||||
}
|
||||
|
||||
if (this->first->isListComprehension()) {
|
||||
if (this->expr->isListComprehension()) {
|
||||
return ValuePtr(flatten(vec));
|
||||
} else {
|
||||
return ValuePtr(vec);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpressionLcFor::print(std::ostream &stream) const
|
||||
void LcFor::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "for(" << this->call_arguments << ") (" << *this->first << ")";
|
||||
stream << "for(" << this->arguments << ") (" << *this->expr << ")";
|
||||
}
|
||||
|
||||
ExpressionLcForC::ExpressionLcForC(const AssignmentList &arglist, const AssignmentList &incrargs, Expression *cond, Expression *expr)
|
||||
: ExpressionLc(cond, expr), call_arguments(arglist), incr_arguments(incrargs)
|
||||
LcForC::LcForC(const AssignmentList &args, const AssignmentList &incrargs, Expression *cond, Expression *expr, const Location &loc)
|
||||
: ListComprehension(loc), arguments(args), incr_arguments(incrargs), cond(cond), expr(expr)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionLcForC::evaluate(const Context *context) const
|
||||
ValuePtr LcForC::evaluate(const Context *context) const
|
||||
{
|
||||
ExperimentalFeatureException::check(Feature::ExperimentalForCExpression);
|
||||
|
||||
Value::VectorType vec;
|
||||
|
||||
Context c(context);
|
||||
evaluate_sequential_assignment(this->call_arguments, &c);
|
||||
evaluate_sequential_assignment(this->arguments, &c);
|
||||
|
||||
unsigned int counter = 0;
|
||||
while (this->first->evaluate(&c)) {
|
||||
vec.push_back(this->second->evaluate(&c));
|
||||
while (this->cond->evaluate(&c)) {
|
||||
vec.push_back(this->expr->evaluate(&c));
|
||||
|
||||
if (counter++ == 1000000) throw RecursionException::create("for loop", "");
|
||||
|
||||
|
|
@ -672,37 +580,37 @@ ValuePtr ExpressionLcForC::evaluate(const Context *context) const
|
|||
c.apply_variables(tmp);
|
||||
}
|
||||
|
||||
if (this->second->isListComprehension()) {
|
||||
if (this->expr->isListComprehension()) {
|
||||
return ValuePtr(flatten(vec));
|
||||
} else {
|
||||
return ValuePtr(vec);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpressionLcForC::print(std::ostream &stream) const
|
||||
void LcForC::print(std::ostream &stream) const
|
||||
{
|
||||
stream
|
||||
<< "for(" << this->call_arguments
|
||||
<< ";" << *this->first
|
||||
<< "for(" << this->arguments
|
||||
<< ";" << *this->cond
|
||||
<< ";" << this->incr_arguments
|
||||
<< ") " << *this->second;
|
||||
<< ") " << *this->expr;
|
||||
}
|
||||
|
||||
ExpressionLcLet::ExpressionLcLet(const AssignmentList &arglist, Expression *expr)
|
||||
: ExpressionLc(expr), call_arguments(arglist)
|
||||
LcLet::LcLet(const AssignmentList &args, Expression *expr, const Location &loc)
|
||||
: ListComprehension(loc), arguments(args), expr(expr)
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr ExpressionLcLet::evaluate(const Context *context) const
|
||||
ValuePtr LcLet::evaluate(const Context *context) const
|
||||
{
|
||||
Context c(context);
|
||||
evaluate_sequential_assignment(this->call_arguments, &c);
|
||||
return this->first->evaluate(&c);
|
||||
evaluate_sequential_assignment(this->arguments, &c);
|
||||
return this->expr->evaluate(&c);
|
||||
}
|
||||
|
||||
void ExpressionLcLet::print(std::ostream &stream) const
|
||||
void LcLet::print(std::ostream &stream) const
|
||||
{
|
||||
stream << "let(" << this->call_arguments << ") (" << *this->first << ")";
|
||||
stream << "let(" << this->arguments << ") (" << *this->expr << ")";
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &stream, const Expression &expr)
|
||||
|
|
|
|||
318
src/expression.h
318
src/expression.h
|
|
@ -1,23 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include "AST.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "value.h"
|
||||
#include "typedefs.h"
|
||||
#include "memory.h"
|
||||
#include "Assignment.h"
|
||||
|
||||
class Expression
|
||||
class Expression : public ASTNode
|
||||
{
|
||||
public:
|
||||
std::vector<Expression*> children;
|
||||
Expression *first;
|
||||
Expression *second;
|
||||
Expression *third;
|
||||
|
||||
Expression();
|
||||
Expression(Expression *expr);
|
||||
Expression(Expression *left, Expression *right);
|
||||
Expression(Expression *expr1, Expression *expr2, Expression *expr3);
|
||||
virtual ~Expression();
|
||||
Expression(const Location &loc) : ASTNode(loc) {}
|
||||
virtual ~Expression() {}
|
||||
|
||||
virtual bool isListComprehension() const;
|
||||
virtual ValuePtr evaluate(const class Context *context) const = 0;
|
||||
|
|
@ -26,264 +21,217 @@ public:
|
|||
|
||||
std::ostream &operator<<(std::ostream &stream, const Expression &expr);
|
||||
|
||||
class ExpressionNot : public Expression
|
||||
class UnaryOp : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionNot(Expression *expr);
|
||||
enum class Op {
|
||||
Not,
|
||||
Negate
|
||||
};
|
||||
|
||||
UnaryOp(Op op, Expression *expr, const Location &loc);
|
||||
virtual ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
|
||||
private:
|
||||
const char *opString() const;
|
||||
|
||||
Op op;
|
||||
shared_ptr<Expression> expr;
|
||||
};
|
||||
|
||||
class ExpressionLogicalAnd : public Expression
|
||||
class BinaryOp : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionLogicalAnd(Expression *left, Expression *right);
|
||||
enum class Op {
|
||||
LogicalAnd,
|
||||
LogicalOr,
|
||||
Multiply,
|
||||
Divide,
|
||||
Modulo,
|
||||
Plus,
|
||||
Minus,
|
||||
Less,
|
||||
LessEqual,
|
||||
Greater,
|
||||
GreaterEqual,
|
||||
Equal,
|
||||
NotEqual
|
||||
};
|
||||
|
||||
BinaryOp(Expression *left, Op op, Expression *right, const Location &loc);
|
||||
virtual ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
|
||||
private:
|
||||
const char *opString() const;
|
||||
|
||||
Op op;
|
||||
shared_ptr<Expression> left;
|
||||
shared_ptr<Expression> right;
|
||||
};
|
||||
|
||||
class TernaryOp : public Expression
|
||||
{
|
||||
public:
|
||||
TernaryOp(Expression *cond, Expression *ifexpr, Expression *elseexpr, const Location &loc);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
|
||||
shared_ptr<Expression> cond;
|
||||
shared_ptr<Expression> ifexpr;
|
||||
shared_ptr<Expression> elseexpr;
|
||||
};
|
||||
|
||||
class ExpressionLogicalOr : public Expression
|
||||
class ArrayLookup : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionLogicalOr(Expression *left, Expression *right);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionMultiply : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionMultiply(Expression *left, Expression *right);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionDivision : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionDivision(Expression *left, Expression *right);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionModulo : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionModulo(Expression *left, Expression *right);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionPlus : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionPlus(Expression *left, Expression *right);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionMinus : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionMinus(Expression *left, Expression *right);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionLess : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionLess(Expression *left, Expression *right);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionLessOrEqual : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionLessOrEqual(Expression *left, Expression *right);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionEqual : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionEqual(Expression *left, Expression *right);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionNotEqual : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionNotEqual(Expression *left, Expression *right);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionGreaterOrEqual : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionGreaterOrEqual(Expression *left, Expression *right);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionGreater : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionGreater(Expression *left, Expression *right);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionTernary : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionTernary(Expression *expr1, Expression *expr2, Expression *expr3);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionArrayLookup : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionArrayLookup(Expression *left, Expression *right);
|
||||
ArrayLookup(Expression *array, Expression *index, const Location &loc);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
shared_ptr<Expression> array;
|
||||
shared_ptr<Expression> index;
|
||||
};
|
||||
|
||||
class ExpressionInvert : public Expression
|
||||
class Literal : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionInvert(Expression *expr);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionConst : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionConst(const ValuePtr &val);
|
||||
Literal(const ValuePtr &val, const Location &loc = Location::NONE);
|
||||
ValuePtr evaluate(const class Context *) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
ValuePtr const_value;
|
||||
ValuePtr value;
|
||||
};
|
||||
|
||||
class ExpressionRange : public Expression
|
||||
class Range : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionRange(Expression *expr1, Expression *expr2);
|
||||
ExpressionRange(Expression *expr1, Expression *expr2, Expression *expr3);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionVector : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionVector(Expression *expr);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionLookup : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionLookup(const std::string &var_name);
|
||||
Range(Expression *begin, Expression *end, const Location &loc);
|
||||
Range(Expression *begin, Expression *step, Expression *end, const Location &loc);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
std::string var_name;
|
||||
shared_ptr<Expression> begin;
|
||||
shared_ptr<Expression> step;
|
||||
shared_ptr<Expression> end;
|
||||
};
|
||||
|
||||
class ExpressionMember : public Expression
|
||||
class Vector : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionMember(Expression *expr, const std::string &member);
|
||||
Vector(const Location &loc);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
void push_back(Expression *expr);
|
||||
private:
|
||||
std::vector<shared_ptr<Expression>> children;
|
||||
};
|
||||
|
||||
class Lookup : public Expression
|
||||
{
|
||||
public:
|
||||
Lookup(const std::string &name, const Location &loc);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
std::string name;
|
||||
};
|
||||
|
||||
class MemberLookup : public Expression
|
||||
{
|
||||
public:
|
||||
MemberLookup(Expression *expr, const std::string &member, const Location &loc);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
shared_ptr<Expression> expr;
|
||||
std::string member;
|
||||
};
|
||||
|
||||
class ExpressionFunctionCall : public Expression
|
||||
class FunctionCall : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionFunctionCall(const std::string &funcname, const AssignmentList &arglist);
|
||||
FunctionCall(const std::string &funcname, const AssignmentList &arglist, const Location &loc);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
public:
|
||||
std::string funcname;
|
||||
AssignmentList call_arguments;
|
||||
std::string name;
|
||||
AssignmentList arguments;
|
||||
};
|
||||
|
||||
class ExpressionLet : public Expression
|
||||
class Let : public Expression
|
||||
{
|
||||
public:
|
||||
ExpressionLet(const AssignmentList &arglist, Expression *expr);
|
||||
Let(const AssignmentList &args, Expression *expr, const Location &loc);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
AssignmentList call_arguments;
|
||||
AssignmentList arguments;
|
||||
shared_ptr<Expression> expr;
|
||||
};
|
||||
|
||||
class ExpressionLc : public Expression
|
||||
class ListComprehension : public Expression
|
||||
{
|
||||
virtual bool isListComprehension() const;
|
||||
public:
|
||||
ExpressionLc(Expression *expr);
|
||||
ExpressionLc(Expression *expr1, Expression *expr2);
|
||||
ListComprehension(const Location &loc);
|
||||
~ListComprehension() = default;
|
||||
};
|
||||
|
||||
class ExpressionLcIf : public ExpressionLc
|
||||
class LcIf : public ListComprehension
|
||||
{
|
||||
public:
|
||||
ExpressionLcIf(Expression *cond, Expression *exprIf, Expression *exprElse);
|
||||
LcIf(Expression *cond, Expression *ifexpr, Expression *elseexpr, const Location &loc);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
Expression *cond;
|
||||
shared_ptr<Expression> cond;
|
||||
shared_ptr<Expression> ifexpr;
|
||||
shared_ptr<Expression> elseexpr;
|
||||
};
|
||||
|
||||
class ExpressionLcFor : public ExpressionLc
|
||||
class LcFor : public ListComprehension
|
||||
{
|
||||
public:
|
||||
ExpressionLcFor(const AssignmentList &arglist, Expression *expr);
|
||||
LcFor(const AssignmentList &args, Expression *expr, const Location &loc);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
AssignmentList call_arguments;
|
||||
AssignmentList arguments;
|
||||
shared_ptr<Expression> expr;
|
||||
};
|
||||
|
||||
class ExpressionLcForC : public ExpressionLc
|
||||
class LcForC : public ListComprehension
|
||||
{
|
||||
public:
|
||||
ExpressionLcForC(const AssignmentList &arglist, const AssignmentList &incrargs, Expression *cond, Expression *expr);
|
||||
LcForC(const AssignmentList &args, const AssignmentList &incrargs, Expression *cond, Expression *expr, const Location &loc);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
AssignmentList call_arguments;
|
||||
AssignmentList arguments;
|
||||
AssignmentList incr_arguments;
|
||||
shared_ptr<Expression> cond;
|
||||
shared_ptr<Expression> expr;
|
||||
};
|
||||
|
||||
class ExpressionLcEach : public ExpressionLc
|
||||
class LcEach : public ListComprehension
|
||||
{
|
||||
public:
|
||||
ExpressionLcEach(Expression *expr);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
};
|
||||
|
||||
class ExpressionLcLet : public ExpressionLc
|
||||
{
|
||||
public:
|
||||
ExpressionLcLet(const AssignmentList &arglist, Expression *expr);
|
||||
LcEach(Expression *expr, const Location &loc);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
AssignmentList call_arguments;
|
||||
shared_ptr<Expression> expr;
|
||||
};
|
||||
|
||||
class LcLet : public ListComprehension
|
||||
{
|
||||
public:
|
||||
LcLet(const AssignmentList &args, Expression *expr, const Location &loc);
|
||||
ValuePtr evaluate(const class Context *context) const;
|
||||
virtual void print(std::ostream &stream) const;
|
||||
private:
|
||||
AssignmentList arguments;
|
||||
shared_ptr<Expression> expr;
|
||||
};
|
||||
|
|
|
|||
137
src/func.cc
137
src/func.cc
|
|
@ -35,6 +35,8 @@
|
|||
#include "printutils.h"
|
||||
#include "stackcheck.h"
|
||||
#include "exceptions.h"
|
||||
#include "memory.h"
|
||||
#include "UserModule.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
|
|
@ -70,137 +72,6 @@ int process_id = getpid();
|
|||
boost::mt19937 deterministic_rng;
|
||||
boost::mt19937 lessdeterministic_rng( std::time(0) + process_id );
|
||||
|
||||
AbstractFunction::~AbstractFunction()
|
||||
{
|
||||
}
|
||||
|
||||
// FIXME: Is this needed?
|
||||
ValuePtr AbstractFunction::evaluate(const Context*, const EvalContext *evalctx) const
|
||||
{
|
||||
(void)evalctx; // unusued parameter
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
std::string AbstractFunction::dump(const std::string &indent, const std::string &name) const
|
||||
{
|
||||
std::stringstream dump;
|
||||
dump << indent << "abstract function " << name << "();\n";
|
||||
return dump.str();
|
||||
}
|
||||
|
||||
Function::Function(const char *name, AssignmentList &definition_arguments, Expression *expr)
|
||||
: name(name), definition_arguments(definition_arguments), expr(expr)
|
||||
{
|
||||
}
|
||||
|
||||
Function::~Function()
|
||||
{
|
||||
delete expr;
|
||||
}
|
||||
|
||||
ValuePtr Function::evaluate(const Context *ctx, const EvalContext *evalctx) const
|
||||
{
|
||||
if (!expr) return ValuePtr::undefined;
|
||||
Context c(ctx);
|
||||
c.setVariables(definition_arguments, evalctx);
|
||||
ValuePtr result = expr->evaluate(&c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string Function::dump(const std::string &indent, const std::string &name) const
|
||||
{
|
||||
std::stringstream dump;
|
||||
dump << indent << "function " << name << "(";
|
||||
for (size_t i=0; i < definition_arguments.size(); i++) {
|
||||
const Assignment &arg = definition_arguments[i];
|
||||
if (i > 0) dump << ", ";
|
||||
dump << arg.first;
|
||||
if (arg.second) dump << " = " << *arg.second;
|
||||
}
|
||||
dump << ") = " << *expr << ";\n";
|
||||
return dump.str();
|
||||
}
|
||||
|
||||
class FunctionTailRecursion : public Function
|
||||
{
|
||||
private:
|
||||
bool invert;
|
||||
ExpressionFunctionCall *call; // memory owned by the main expression
|
||||
Expression *endexpr; // memory owned by the main expression
|
||||
|
||||
public:
|
||||
FunctionTailRecursion(const char *name, AssignmentList &definition_arguments, Expression *expr, ExpressionFunctionCall *call, Expression *endexpr, bool invert);
|
||||
virtual ~FunctionTailRecursion();
|
||||
|
||||
virtual ValuePtr evaluate(const Context *ctx, const EvalContext *evalctx) const;
|
||||
};
|
||||
|
||||
FunctionTailRecursion::FunctionTailRecursion(const char *name, AssignmentList &definition_arguments, Expression *expr, ExpressionFunctionCall *call, Expression *endexpr, bool invert)
|
||||
: Function(name, definition_arguments, expr), invert(invert), call(call), endexpr(endexpr)
|
||||
{
|
||||
}
|
||||
|
||||
FunctionTailRecursion::~FunctionTailRecursion()
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr FunctionTailRecursion::evaluate(const Context *ctx, const EvalContext *evalctx) const
|
||||
{
|
||||
if (!expr) return ValuePtr::undefined;
|
||||
|
||||
Context c(ctx);
|
||||
c.setVariables(definition_arguments, evalctx);
|
||||
|
||||
EvalContext ec(&c, call->call_arguments);
|
||||
Context tmp(&c);
|
||||
unsigned int counter = 0;
|
||||
while (invert ^ expr->first->evaluate(&c)) {
|
||||
tmp.setVariables(definition_arguments, &ec);
|
||||
c.apply_variables(tmp);
|
||||
|
||||
if (counter++ == 1000000) throw RecursionException::create("function", this->name);
|
||||
}
|
||||
|
||||
ValuePtr result = endexpr->evaluate(&c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Function * Function::create(const char *name, AssignmentList &definition_arguments, Expression *expr)
|
||||
{
|
||||
if (dynamic_cast<ExpressionTernary *>(expr)) {
|
||||
ExpressionFunctionCall *f1 = dynamic_cast<ExpressionFunctionCall *>(expr->second);
|
||||
ExpressionFunctionCall *f2 = dynamic_cast<ExpressionFunctionCall *>(expr->third);
|
||||
if (f1 && !f2) {
|
||||
if (name == f1->funcname) {
|
||||
return new FunctionTailRecursion(name, definition_arguments, expr, f1, expr->third, false);
|
||||
}
|
||||
} else if (f2 && !f1) {
|
||||
if (name == f2->funcname) {
|
||||
return new FunctionTailRecursion(name, definition_arguments, expr, f2, expr->second, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Function(name, definition_arguments, expr);
|
||||
}
|
||||
|
||||
BuiltinFunction::~BuiltinFunction()
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr BuiltinFunction::evaluate(const Context *ctx, const EvalContext *evalctx) const
|
||||
{
|
||||
return eval_func(ctx, evalctx);
|
||||
}
|
||||
|
||||
std::string BuiltinFunction::dump(const std::string &indent, const std::string &name) const
|
||||
{
|
||||
std::stringstream dump;
|
||||
dump << indent << "builtin function " << name << "();\n";
|
||||
return dump.str();
|
||||
}
|
||||
|
||||
static inline double deg2rad(double x)
|
||||
{
|
||||
return x * M_PI / 180.0;
|
||||
|
|
@ -912,7 +783,7 @@ ValuePtr builtin_parent_module(const Context *, const EvalContext *evalctx)
|
|||
{
|
||||
int n;
|
||||
double d;
|
||||
int s = Module::stack_size();
|
||||
int s = UserModule::stack_size();
|
||||
if (evalctx->numArgs() == 0)
|
||||
d=1; // parent module
|
||||
else if (evalctx->numArgs() == 1) {
|
||||
|
|
@ -930,7 +801,7 @@ ValuePtr builtin_parent_module(const Context *, const EvalContext *evalctx)
|
|||
PRINTB("WARNING: Parent module index (%d) greater than the number of modules on the stack", n);
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
return ValuePtr(Module::stack_element(s - 1 - n));
|
||||
return ValuePtr(UserModule::stack_element(s - 1 - n));
|
||||
}
|
||||
|
||||
ValuePtr builtin_norm(const Context *, const EvalContext *evalctx)
|
||||
|
|
|
|||
141
src/function.cc
Normal file
141
src/function.cc
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* OpenSCAD (www.openscad.org)
|
||||
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
|
||||
* Marius Kintel <marius@kintel.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* As a special exception, you have permission to link this program
|
||||
* with the CGAL library and distribute executables, as long as you
|
||||
* follow the requirements of the GNU GPL in regard to all of the
|
||||
* software in the executable aside from CGAL.
|
||||
*
|
||||
* 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 "function.h"
|
||||
#include "evalcontext.h"
|
||||
#include "expression.h"
|
||||
|
||||
AbstractFunction::~AbstractFunction()
|
||||
{
|
||||
}
|
||||
|
||||
UserFunction::UserFunction(const char *name, AssignmentList &definition_arguments, shared_ptr<Expression> expr, const Location &loc)
|
||||
: ASTNode(loc), name(name), definition_arguments(definition_arguments), expr(expr)
|
||||
{
|
||||
}
|
||||
|
||||
UserFunction::~UserFunction()
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr UserFunction::evaluate(const Context *ctx, const EvalContext *evalctx) const
|
||||
{
|
||||
if (!expr) return ValuePtr::undefined;
|
||||
Context c(ctx);
|
||||
c.setVariables(definition_arguments, evalctx);
|
||||
ValuePtr result = expr->evaluate(&c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string UserFunction::dump(const std::string &indent, const std::string &name) const
|
||||
{
|
||||
std::stringstream dump;
|
||||
dump << indent << "function " << name << "(";
|
||||
for (size_t i=0; i < definition_arguments.size(); i++) {
|
||||
const Assignment &arg = definition_arguments[i];
|
||||
if (i > 0) dump << ", ";
|
||||
dump << arg.name;
|
||||
if (arg.expr) dump << " = " << *arg.expr;
|
||||
}
|
||||
dump << ") = " << *expr << ";\n";
|
||||
return dump.str();
|
||||
}
|
||||
|
||||
class FunctionTailRecursion : public UserFunction
|
||||
{
|
||||
private:
|
||||
bool invert;
|
||||
shared_ptr<TernaryOp> op;
|
||||
shared_ptr<FunctionCall> call;
|
||||
shared_ptr<Expression> endexpr;
|
||||
|
||||
public:
|
||||
FunctionTailRecursion(const char *name, AssignmentList &definition_arguments,
|
||||
shared_ptr<TernaryOp> expr, shared_ptr<FunctionCall> call,
|
||||
shared_ptr<Expression> endexpr, bool invert,
|
||||
const Location &loc)
|
||||
: UserFunction(name, definition_arguments, expr, loc),
|
||||
invert(invert), op(expr), call(call), endexpr(endexpr) {
|
||||
}
|
||||
|
||||
virtual ~FunctionTailRecursion() { }
|
||||
|
||||
virtual ValuePtr evaluate(const Context *ctx, const EvalContext *evalctx) const {
|
||||
if (!expr) return ValuePtr::undefined;
|
||||
|
||||
Context c(ctx);
|
||||
c.setVariables(definition_arguments, evalctx);
|
||||
|
||||
EvalContext ec(&c, call->arguments);
|
||||
Context tmp(&c);
|
||||
unsigned int counter = 0;
|
||||
while (invert ^ this->op->cond->evaluate(&c)) {
|
||||
tmp.setVariables(definition_arguments, &ec);
|
||||
c.apply_variables(tmp);
|
||||
|
||||
if (counter++ == 1000000) throw RecursionException::create("function", this->name);
|
||||
}
|
||||
|
||||
ValuePtr result = endexpr->evaluate(&c);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
UserFunction *UserFunction::create(const char *name, AssignmentList &definition_arguments, shared_ptr<Expression> expr, const Location &loc)
|
||||
{
|
||||
if (shared_ptr<TernaryOp> ternary = dynamic_pointer_cast<TernaryOp>(expr)) {
|
||||
shared_ptr<FunctionCall> ifcall = dynamic_pointer_cast<FunctionCall>(ternary->ifexpr);
|
||||
shared_ptr<FunctionCall> elsecall = dynamic_pointer_cast<FunctionCall>(ternary->elseexpr);
|
||||
if (ifcall && !elsecall) {
|
||||
if (name == ifcall->name) {
|
||||
return new FunctionTailRecursion(name, definition_arguments, ternary, ifcall, ternary->elseexpr, false, loc);
|
||||
}
|
||||
} else if (elsecall && !ifcall) {
|
||||
if (name == elsecall->name) {
|
||||
return new FunctionTailRecursion(name, definition_arguments, ternary, elsecall, ternary->ifexpr, true, loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new UserFunction(name, definition_arguments, expr, loc);
|
||||
}
|
||||
|
||||
BuiltinFunction::~BuiltinFunction()
|
||||
{
|
||||
}
|
||||
|
||||
ValuePtr BuiltinFunction::evaluate(const Context *ctx, const EvalContext *evalctx) const
|
||||
{
|
||||
return eval_func(ctx, evalctx);
|
||||
}
|
||||
|
||||
std::string BuiltinFunction::dump(const std::string &indent, const std::string &name) const
|
||||
{
|
||||
std::stringstream dump;
|
||||
dump << indent << "builtin function " << name << "();\n";
|
||||
return dump.str();
|
||||
}
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "AST.h"
|
||||
#include "value.h"
|
||||
#include "typedefs.h"
|
||||
#include "Assignment.h"
|
||||
#include "feature.h"
|
||||
|
||||
#include <string>
|
||||
|
|
@ -12,13 +13,13 @@ class AbstractFunction
|
|||
private:
|
||||
const Feature *feature;
|
||||
public:
|
||||
AbstractFunction() : feature(NULL) {}
|
||||
AbstractFunction(const Feature& feature) : feature(&feature) {}
|
||||
AbstractFunction() : feature(NULL) {}
|
||||
virtual ~AbstractFunction();
|
||||
virtual bool is_experimental() const { return feature != NULL; }
|
||||
virtual bool is_enabled() const { return (feature == NULL) || feature->is_enabled(); }
|
||||
virtual ValuePtr evaluate(const class Context *ctx, const class EvalContext *evalctx) const;
|
||||
virtual std::string dump(const std::string &indent, const std::string &name) const;
|
||||
virtual ValuePtr evaluate(const class Context *ctx, const class EvalContext *evalctx) const = 0;
|
||||
virtual std::string dump(const std::string &indent, const std::string &name) const = 0;
|
||||
};
|
||||
|
||||
class BuiltinFunction : public AbstractFunction
|
||||
|
|
@ -35,19 +36,19 @@ public:
|
|||
virtual std::string dump(const std::string &indent, const std::string &name) const;
|
||||
};
|
||||
|
||||
class Function : public AbstractFunction
|
||||
class UserFunction : public AbstractFunction, public ASTNode
|
||||
{
|
||||
public:
|
||||
std::string name;
|
||||
std::string name;
|
||||
AssignmentList definition_arguments;
|
||||
|
||||
Expression *expr;
|
||||
shared_ptr<Expression> expr;
|
||||
|
||||
Function(const char *name, AssignmentList &definition_arguments, Expression *expr);
|
||||
virtual ~Function();
|
||||
UserFunction(const char *name, AssignmentList &definition_arguments, shared_ptr<Expression> expr, const Location &loc);
|
||||
virtual ~UserFunction();
|
||||
|
||||
virtual ValuePtr evaluate(const Context *ctx, const EvalContext *evalctx) const;
|
||||
virtual std::string dump(const std::string &indent, const std::string &name) const;
|
||||
|
||||
static Function * create(const char *name, AssignmentList &definition_arguments, Expression *expr);
|
||||
static UserFunction *create(const char *name, AssignmentList &definition_arguments, shared_ptr<Expression> expr, const Location &loc);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "importnode.h"
|
||||
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "polyset.h"
|
||||
#include "Polygon2d.h"
|
||||
#include "evalcontext.h"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "node.h"
|
||||
#include "visitor.h"
|
||||
#include "value.h"
|
||||
|
||||
enum import_type_e {
|
||||
|
|
@ -14,10 +13,8 @@ enum import_type_e {
|
|||
class ImportNode : public LeafNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
ImportNode(const ModuleInstantiation *mi, import_type_e type) : LeafNode(mi), type(type) { }
|
||||
virtual Response accept(class State &state, Visitor &visitor) const {
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
virtual std::string toString() const;
|
||||
virtual std::string name() const;
|
||||
|
||||
|
|
|
|||
29
src/lexer.l
29
src/lexer.l
|
|
@ -27,13 +27,12 @@
|
|||
%{
|
||||
|
||||
#include <glib.h>
|
||||
#include "typedefs.h"
|
||||
#include "handle_dep.h"
|
||||
#include "printutils.h"
|
||||
#include "parsersettings.h"
|
||||
#include "Assignment.h"
|
||||
#include "parser_yacc.h"
|
||||
#include "module.h"
|
||||
#include<iostream>
|
||||
#include "FileModule.h"
|
||||
#include <assert.h>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
|
@ -89,6 +88,15 @@ std::vector<std::string> openfilenames;
|
|||
std::string filename;
|
||||
std::string filepath;
|
||||
|
||||
extern YYLTYPE parserlloc;
|
||||
#define yylloc parserlloc
|
||||
|
||||
int yycolumn = 1;
|
||||
#define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno; \
|
||||
yylloc.first_column = yycolumn; yylloc.last_column = yycolumn+yyleng-1; \
|
||||
yycolumn += yyleng;
|
||||
|
||||
|
||||
%}
|
||||
|
||||
%option yylineno
|
||||
|
|
@ -203,18 +211,11 @@ use[ \t\r\n>]*"<" { BEGIN(cond_use); }
|
|||
|
||||
[\n\r\t ]
|
||||
|
||||
[\n]+"//" { BEGIN(cond_lcomment); stringcontents.clear(); return DCOMMENT;}
|
||||
|
||||
\/\/ { BEGIN(cond_lcomment); stringcontents.clear(); return COMMENT;}
|
||||
\/\/ BEGIN(cond_lcomment);
|
||||
<cond_lcomment>{
|
||||
\n { BEGIN(INITIAL);
|
||||
parserlval.text = strdup(stringcontents.c_str());
|
||||
return CTOK_STRING; }
|
||||
{UNICODE} {
|
||||
parser_error_pos -= strlen(lexertext) - 1;
|
||||
stringcontents += lexertext; }
|
||||
[^\n] { stringcontents += lexertext;}
|
||||
|
||||
\n { BEGIN(INITIAL); }
|
||||
{UNICODE} { parser_error_pos -= strlen(lexertext) - 1; }
|
||||
[^\n]
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "linearextrudenode.h"
|
||||
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "evalcontext.h"
|
||||
#include "printutils.h"
|
||||
#include "fileutils.h"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "node.h"
|
||||
#include "visitor.h"
|
||||
#include "value.h"
|
||||
|
||||
class LinearExtrudeNode : public AbstractPolyNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
LinearExtrudeNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) {
|
||||
convexity = slices = 0;
|
||||
fn = fs = fa = height = twist = 0;
|
||||
|
|
@ -14,9 +14,6 @@ public:
|
|||
scale_x = scale_y = 1;
|
||||
center = has_twist = false;
|
||||
}
|
||||
virtual Response accept(class State &state, Visitor &visitor) const {
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
virtual std::string toString() const;
|
||||
virtual std::string name() const { return "linear_extrude"; }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "localscope.h"
|
||||
#include "modcontext.h"
|
||||
#include "module.h"
|
||||
#include "typedefs.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "expression.h"
|
||||
#include "function.h"
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ std::string LocalScope::dump(const std::string &indent) const
|
|||
dump << m.second->dump(indent, m.first);
|
||||
}
|
||||
for(const auto &ass : this->assignments) {
|
||||
dump << indent << ass.first << " = " << *ass.second << ";\n";
|
||||
dump << indent << ass.name << " = " << *ass.expr << ";\n";
|
||||
}
|
||||
for(const auto &inst : this->children) {
|
||||
dump << inst->dump(indent);
|
||||
|
|
@ -61,6 +61,6 @@ std::vector<AbstractNode*> LocalScope::instantiateChildren(const Context *evalct
|
|||
void LocalScope::apply(Context &ctx) const
|
||||
{
|
||||
for(const auto &ass : this->assignments) {
|
||||
ctx.set_variable(ass.first, ass.second->evaluate(&ctx));
|
||||
ctx.set_variable(ass.name, ass.expr->evaluate(&ctx));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "Assignment.h"
|
||||
#include <unordered_map>
|
||||
|
||||
class LocalScope
|
||||
|
|
@ -12,11 +12,11 @@ public:
|
|||
size_t numElements() const { return assignments.size() + children.size(); }
|
||||
std::string dump(const std::string &indent) const;
|
||||
std::vector<class AbstractNode*> instantiateChildren(const class Context *evalctx) const;
|
||||
void addChild(ModuleInstantiation *ch);
|
||||
void addChild(class ModuleInstantiation *ch);
|
||||
void apply(Context &ctx) const;
|
||||
|
||||
AssignmentList assignments;
|
||||
ModuleInstantiationList children;
|
||||
std::vector<ModuleInstantiation*> children;
|
||||
typedef std::unordered_map<std::string, class AbstractFunction*> FunctionContainer;
|
||||
FunctionContainer functions;
|
||||
typedef std::unordered_map<std::string, class AbstractModule*> AbstractModuleContainer;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "openscad.h"
|
||||
#include "GeometryCache.h"
|
||||
|
|
@ -1715,13 +1716,91 @@ void MainWindow::compileTopLevelDocument()
|
|||
const char* fname =
|
||||
this->fileName.isEmpty() ? "" : fnameba;
|
||||
this->root_module = parse(fulltext.c_str(), fs::path(fname), false);
|
||||
|
||||
|
||||
if(this->root_module!=NULL)
|
||||
addparameter(fulltext.c_str());
|
||||
|
||||
this->parameterWidget->setParameters(this->root_module);
|
||||
this->parameterWidget->applyParameters(this->root_module);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::addparameter(const char *fulltext){
|
||||
|
||||
for (AssignmentList::iterator it = this->root_module->scope.assignments.begin();it != this->root_module->scope.assignments.end();it++) {
|
||||
|
||||
//get loaction of assignment node
|
||||
const Location locate=(*it).location();
|
||||
int loc =locate.firstLine();
|
||||
|
||||
// makeing list to add annotations
|
||||
AnnotationList *annotationList = new AnnotationList();
|
||||
AssignmentList *assignments;
|
||||
|
||||
//extracting the parameter
|
||||
string name = getParameter(std::string(fulltext),loc);
|
||||
if(name!= " " ){
|
||||
|
||||
//getting the node for parameter annnotataion
|
||||
assignments=parser(name.c_str());
|
||||
if(assignments!=NULL){
|
||||
const Annotation *Parameter;
|
||||
Parameter=Annotation::create("Parameter",*assignments);
|
||||
|
||||
// adding parameter to the list
|
||||
annotationList->push_back(*Parameter);
|
||||
}
|
||||
}
|
||||
|
||||
//extracting the description
|
||||
name = getParameter(std::string(fulltext),loc-1);
|
||||
if(name!= " "){
|
||||
//creating node for description
|
||||
assignments=new AssignmentList();
|
||||
Expression *expr;
|
||||
expr=new Literal(ValuePtr(std::string(name.c_str())));
|
||||
Assignment *assign;
|
||||
assign=new Assignment("", shared_ptr<Expression>(expr));
|
||||
assignments->push_back(*assign);
|
||||
|
||||
const Annotation * Description;
|
||||
Description=Annotation::create("Description", *assignments);
|
||||
annotationList->push_back(*Description);
|
||||
}
|
||||
|
||||
(*it).add_annotations(annotationList);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
string MainWindow::getParameter(string fulltext, int loc){
|
||||
int chara=0;
|
||||
|
||||
for(; chara<fulltext.length() ; chara++){
|
||||
if(fulltext[chara]=='\n')
|
||||
loc--;
|
||||
if(loc==1)
|
||||
break;
|
||||
}
|
||||
int len=chara+1;
|
||||
while(fulltext[len]!='\n'){
|
||||
len++;
|
||||
|
||||
}
|
||||
string str2 = fulltext.substr(chara,len-chara);
|
||||
int start= str2.find("//");
|
||||
if(start<0 || start+2>str2.length()){
|
||||
return " ";
|
||||
}
|
||||
return str2.substr(start+2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void MainWindow::checkAutoReload()
|
||||
{
|
||||
if (!this->fileName.isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
#include "math.h"
|
||||
|
||||
#include "modcontext.h"
|
||||
#include "module.h"
|
||||
#include "UserModule.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "expression.h"
|
||||
#include "function.h"
|
||||
#include "printutils.h"
|
||||
|
|
@ -64,14 +65,14 @@ void ModuleContext::evaluateAssignments(const AssignmentList &assignments)
|
|||
}
|
||||
#endif
|
||||
|
||||
void ModuleContext::initializeModule(const class Module &module)
|
||||
void ModuleContext::initializeModule(const UserModule &module)
|
||||
{
|
||||
this->setVariables(module.definition_arguments, evalctx);
|
||||
// FIXME: Don't access module members directly
|
||||
this->functions_p = &module.scope.functions;
|
||||
this->modules_p = &module.scope.modules;
|
||||
for(const auto &ass : module.scope.assignments) {
|
||||
this->set_variable(ass.first, ass.second->evaluate(this));
|
||||
this->set_variable(ass.name, ass.expr->evaluate(this));
|
||||
}
|
||||
|
||||
// Experimental code. See issue #399
|
||||
|
|
@ -89,7 +90,7 @@ void ModuleContext::registerBuiltin()
|
|||
this->functions_p = &scope.functions;
|
||||
this->modules_p = &scope.modules;
|
||||
for(const auto &ass : scope.assignments) {
|
||||
this->set_variable(ass.first, ass.second->evaluate(this));
|
||||
this->set_variable(ass.name, ass.expr->evaluate(this));
|
||||
}
|
||||
|
||||
this->set_constant("PI", ValuePtr(M_PI));
|
||||
|
|
@ -152,11 +153,11 @@ std::string ModuleContext::dump(const AbstractModule *mod, const ModuleInstantia
|
|||
s << boost::format("ModuleContext: %p (%p)") % this % this->parent;
|
||||
s << boost::format(" document path: %s") % this->document_path;
|
||||
if (mod) {
|
||||
const Module *m = dynamic_cast<const Module*>(mod);
|
||||
const UserModule *m = dynamic_cast<const UserModule*>(mod);
|
||||
if (m) {
|
||||
s << " module args:";
|
||||
for(const auto &arg : m->definition_arguments) {
|
||||
s << boost::format(" %s = %s") % arg.first % variables[arg.first];
|
||||
s << boost::format(" %s = %s") % arg.name % variables[arg.name];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -184,7 +185,6 @@ FileContext::FileContext(const class FileModule &module, const Context *parent)
|
|||
ValuePtr FileContext::sub_evaluate_function(const std::string &name,
|
||||
const EvalContext *evalctx,
|
||||
FileModule *usedmod) const
|
||||
|
||||
{
|
||||
FileContext ctx(*usedmod, this->parent);
|
||||
ctx.initializeModule(*usedmod);
|
||||
|
|
@ -235,3 +235,13 @@ AbstractNode *FileContext::instantiate_module(const ModuleInstantiation &inst, E
|
|||
|
||||
return ModuleContext::instantiate_module(inst, evalctx);
|
||||
}
|
||||
|
||||
void FileContext::initializeModule(const class FileModule &module)
|
||||
{
|
||||
// FIXME: Don't access module members directly
|
||||
this->functions_p = &module.scope.functions;
|
||||
this->modules_p = &module.scope.modules;
|
||||
for(const auto &ass : module.scope.assignments) {
|
||||
this->set_variable(ass.name, ass.expr->evaluate(this));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "context.h"
|
||||
#include "module.h"
|
||||
#include "FileModule.h"
|
||||
|
||||
/*!
|
||||
This holds the context for a Module definition; keeps track of
|
||||
This holds the context for a UserModule definition; keeps track of
|
||||
global variables, submodules and functions defined inside a module.
|
||||
|
||||
NB! every .scad file defines a FileModule holding the contents of the file.
|
||||
|
|
@ -15,7 +15,7 @@ public:
|
|||
ModuleContext(const Context *parent = NULL, const EvalContext *evalctx = NULL);
|
||||
virtual ~ModuleContext();
|
||||
|
||||
void initializeModule(const Module &m);
|
||||
void initializeModule(const class UserModule &m);
|
||||
void registerBuiltin();
|
||||
virtual ValuePtr evaluate_function(const std::string &name,
|
||||
const EvalContext *evalctx) const;
|
||||
|
|
@ -42,8 +42,9 @@ private:
|
|||
class FileContext : public ModuleContext
|
||||
{
|
||||
public:
|
||||
FileContext(const class FileModule &module, const Context *parent);
|
||||
FileContext(const FileModule &module, const Context *parent);
|
||||
virtual ~FileContext() {}
|
||||
void initializeModule(const FileModule &module);
|
||||
virtual ValuePtr evaluate_function(const std::string &name,
|
||||
const EvalContext *evalctx) const;
|
||||
virtual AbstractNode *instantiate_module(const ModuleInstantiation &inst,
|
||||
|
|
|
|||
351
src/module.cc
351
src/module.cc
|
|
@ -25,40 +25,14 @@
|
|||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "ModuleCache.h"
|
||||
#include "node.h"
|
||||
#include "builtin.h"
|
||||
#include "modcontext.h"
|
||||
#include "evalcontext.h"
|
||||
#include "expression.h"
|
||||
#include "function.h"
|
||||
#include "printutils.h"
|
||||
#include "parsersettings.h"
|
||||
#include "exceptions.h"
|
||||
#include "stackcheck.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
namespace fs = boost::filesystem;
|
||||
#include "boosty.h"
|
||||
#include "FontCache.h"
|
||||
#include "context.h"
|
||||
#include "value.h"
|
||||
#include <sstream>
|
||||
#include <sys/stat.h>
|
||||
|
||||
AbstractModule::~AbstractModule()
|
||||
{
|
||||
}
|
||||
|
||||
AbstractNode *GroupModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||
{
|
||||
(void)ctx; // avoid unusued parameter warning
|
||||
|
||||
AbstractNode *node = new GroupNode(inst);
|
||||
|
||||
node->children = inst->instantiateChildren(evalctx);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
double AbstractModule::lookup_double_variable_with_default(Context &c, std::string variable, double def) const
|
||||
{
|
||||
ValuePtr v = c.lookup_variable(variable, true);
|
||||
|
|
@ -78,324 +52,3 @@ std::string AbstractModule::dump(const std::string &indent, const std::string &n
|
|||
return dump.str();
|
||||
}
|
||||
|
||||
ModuleInstantiation::~ModuleInstantiation()
|
||||
{
|
||||
}
|
||||
|
||||
IfElseModuleInstantiation::~IfElseModuleInstantiation()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the absolute path to the given filename, unless it's empty.
|
||||
|
||||
NB! This will actually search for the file, to be backwards compatible with <= 2013.01
|
||||
(see issue #217)
|
||||
*/
|
||||
std::string ModuleInstantiation::getAbsolutePath(const std::string &filename) const
|
||||
{
|
||||
if (!filename.empty() && !boosty::is_absolute(fs::path(filename))) {
|
||||
return boosty::absolute(fs::path(this->modpath) / filename).string();
|
||||
}
|
||||
else {
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
|
||||
std::string ModuleInstantiation::dump(const std::string &indent) const
|
||||
{
|
||||
std::stringstream dump;
|
||||
dump << indent;
|
||||
dump << modname + "(";
|
||||
for (size_t i=0; i < this->arguments.size(); i++) {
|
||||
const Assignment &arg = this->arguments[i];
|
||||
if (i > 0) dump << ", ";
|
||||
if (!arg.first.empty()) dump << arg.first << " = ";
|
||||
dump << *arg.second;
|
||||
}
|
||||
if (scope.numElements() == 0) {
|
||||
dump << ");\n";
|
||||
} else if (scope.numElements() == 1) {
|
||||
dump << ") ";
|
||||
dump << scope.dump("");
|
||||
} else {
|
||||
dump << ") {\n";
|
||||
dump << scope.dump(indent + "\t");
|
||||
dump << indent << "}\n";
|
||||
}
|
||||
return dump.str();
|
||||
}
|
||||
|
||||
std::string IfElseModuleInstantiation::dump(const std::string &indent) const
|
||||
{
|
||||
std::stringstream dump;
|
||||
dump << ModuleInstantiation::dump(indent);
|
||||
dump << indent;
|
||||
if (else_scope.numElements() > 0) {
|
||||
dump << indent << "else ";
|
||||
if (else_scope.numElements() == 1) {
|
||||
dump << else_scope.dump("");
|
||||
}
|
||||
else {
|
||||
dump << "{\n";
|
||||
dump << else_scope.dump(indent + "\t");
|
||||
dump << indent << "}\n";
|
||||
}
|
||||
}
|
||||
return dump.str();
|
||||
}
|
||||
|
||||
AbstractNode *ModuleInstantiation::evaluate(const Context *ctx) const
|
||||
{
|
||||
EvalContext c(ctx, this->arguments, &this->scope);
|
||||
|
||||
#if 0 && DEBUG
|
||||
PRINT("New eval ctx:");
|
||||
c.dump(NULL, this);
|
||||
#endif
|
||||
|
||||
AbstractNode *node = ctx->instantiate_module(*this, &c); // Passes c as evalctx
|
||||
return node;
|
||||
}
|
||||
|
||||
std::vector<AbstractNode*> ModuleInstantiation::instantiateChildren(const Context *evalctx) const
|
||||
{
|
||||
return this->scope.instantiateChildren(evalctx);
|
||||
}
|
||||
|
||||
std::vector<AbstractNode*> IfElseModuleInstantiation::instantiateElseChildren(const Context *evalctx) const
|
||||
{
|
||||
return this->else_scope.instantiateChildren(evalctx);
|
||||
}
|
||||
|
||||
std::deque<std::string> Module::module_stack;
|
||||
|
||||
Module::~Module()
|
||||
{
|
||||
}
|
||||
|
||||
void Module::add_annotations(AnnotationList *annotations)
|
||||
{
|
||||
for (AnnotationList::iterator it = annotations->begin();it != annotations->end();it++) {
|
||||
this->annotations.insert(std::pair<const std::string, Annotation *>((*it).get_name(), &(*it)));
|
||||
}
|
||||
}
|
||||
|
||||
bool Module::has_annotations() const
|
||||
{
|
||||
return !annotations.empty();
|
||||
}
|
||||
|
||||
const Annotation * Module::annotation(const std::string &name) const
|
||||
{
|
||||
AnnotationMap::const_iterator it = annotations.find(name);
|
||||
return it == annotations.end() ? NULL : (*it).second;
|
||||
}
|
||||
|
||||
AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx) const
|
||||
{
|
||||
if (StackCheck::inst()->check()) {
|
||||
throw RecursionException::create("module", inst->name());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// At this point we know that nobody will modify the dependencies of the local scope
|
||||
// passed to this instance, so we can populate the context
|
||||
inst->scope.apply(*evalctx);
|
||||
|
||||
ModuleContext c(ctx, evalctx);
|
||||
// set $children first since we might have variables depending on it
|
||||
c.set_variable("$children", ValuePtr(double(inst->scope.children.size())));
|
||||
module_stack.push_back(inst->name());
|
||||
c.set_variable("$parent_modules", ValuePtr(double(module_stack.size())));
|
||||
c.initializeModule(*this);
|
||||
// FIXME: Set document path to the path of the module
|
||||
#if 0 && DEBUG
|
||||
c.dump(this, inst);
|
||||
#endif
|
||||
|
||||
AbstractNode *node = new GroupNode(inst);
|
||||
std::vector<AbstractNode *> instantiatednodes = this->scope.instantiateChildren(&c);
|
||||
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
||||
module_stack.pop_back();
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
std::string Module::dump(const std::string &indent, const std::string &name) const
|
||||
{
|
||||
std::stringstream dump;
|
||||
std::string tab;
|
||||
if (!name.empty()) {
|
||||
dump << indent << "module " << name << "(";
|
||||
for (size_t i=0; i < this->definition_arguments.size(); i++) {
|
||||
const Assignment &arg = this->definition_arguments[i];
|
||||
if (i > 0) dump << ", ";
|
||||
dump << arg.first;
|
||||
if (arg.second) dump << " = " << *arg.second;
|
||||
}
|
||||
dump << ") {\n";
|
||||
tab = "\t";
|
||||
}
|
||||
dump << scope.dump(indent + tab);
|
||||
if (!name.empty()) {
|
||||
dump << indent << "}\n";
|
||||
}
|
||||
return dump.str();
|
||||
}
|
||||
|
||||
FileModule::~FileModule()
|
||||
{
|
||||
delete context;
|
||||
}
|
||||
|
||||
void FileModule::registerUse(const std::string path) {
|
||||
std::string extraw = boosty::extension_str(fs::path(path));
|
||||
std::string ext = boost::algorithm::to_lower_copy(extraw);
|
||||
|
||||
if ((ext == ".otf") || (ext == ".ttf")) {
|
||||
if (fs::is_regular(path)) {
|
||||
FontCache::instance()->register_font_file(path);
|
||||
} else {
|
||||
PRINTB("ERROR: Can't read font with path '%s'", path);
|
||||
}
|
||||
} else {
|
||||
usedlibs.insert(path);
|
||||
}
|
||||
}
|
||||
|
||||
void FileModule::registerInclude(const std::string &localpath,
|
||||
const std::string &fullpath)
|
||||
{
|
||||
struct stat st;
|
||||
memset(&st, 0, sizeof(struct stat));
|
||||
bool valid = stat(fullpath.c_str(), &st) == 0;
|
||||
IncludeFile inc = {fullpath, valid, st.st_mtime};
|
||||
this->includes[localpath] = inc;
|
||||
}
|
||||
|
||||
bool FileModule::includesChanged() const
|
||||
{
|
||||
for(const auto &item : this->includes) {
|
||||
if (include_modified(item.second)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FileModule::include_modified(const IncludeFile &inc) const
|
||||
{
|
||||
struct stat st;
|
||||
memset(&st, 0, sizeof(struct stat));
|
||||
|
||||
fs::path fullpath = find_valid_path(this->path, inc.filename);
|
||||
bool valid = !fullpath.empty() ? (stat(boosty::stringy(fullpath).c_str(), &st) == 0) : false;
|
||||
|
||||
if (valid && !inc.valid) return true; // Detect appearance of file but not removal
|
||||
if (valid && st.st_mtime > inc.mtime) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Check if any dependencies have been modified and recompile them.
|
||||
Returns true if anything was recompiled.
|
||||
*/
|
||||
bool FileModule::handleDependencies()
|
||||
{
|
||||
if (this->is_handling_dependencies) return false;
|
||||
this->is_handling_dependencies = true;
|
||||
|
||||
bool somethingchanged = false;
|
||||
std::vector<std::pair<std::string,std::string>> updates;
|
||||
|
||||
// If a lib in usedlibs was previously missing, we need to relocate it
|
||||
// by searching the applicable paths. We can identify a previously missing module
|
||||
// as it will have a relative path.
|
||||
for(auto filename : this->usedlibs) {
|
||||
|
||||
bool wasmissing = false;
|
||||
bool found = true;
|
||||
|
||||
// Get an absolute filename for the module
|
||||
if (!boosty::is_absolute(filename)) {
|
||||
wasmissing = true;
|
||||
fs::path fullpath = find_valid_path(this->path, filename);
|
||||
if (!fullpath.empty()) {
|
||||
updates.push_back(std::make_pair(filename, boosty::stringy(fullpath)));
|
||||
filename = boosty::stringy(fullpath);
|
||||
}
|
||||
else {
|
||||
found = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
bool wascached = ModuleCache::instance()->isCached(filename);
|
||||
FileModule *oldmodule = ModuleCache::instance()->lookup(filename);
|
||||
FileModule *newmodule;
|
||||
bool changed = ModuleCache::instance()->evaluate(filename, newmodule);
|
||||
// Detect appearance but not removal of files, and keep old module
|
||||
// on compile errors (FIXME: Is this correct behavior?)
|
||||
if (changed) {
|
||||
PRINTDB(" %s: %p -> %p", filename % oldmodule % newmodule);
|
||||
}
|
||||
somethingchanged |= changed;
|
||||
// Only print warning if we're not part of an automatic reload
|
||||
if (!newmodule && !wascached && !wasmissing) {
|
||||
PRINTB_NOCACHE("WARNING: Failed to compile library '%s'.", filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Relative filenames which were located is reinserted as absolute filenames
|
||||
typedef std::pair<std::string,std::string> stringpair;
|
||||
for(const auto &files : updates) {
|
||||
this->usedlibs.erase(files.first);
|
||||
this->usedlibs.insert(files.second);
|
||||
}
|
||||
this->is_handling_dependencies = false;
|
||||
return somethingchanged;
|
||||
}
|
||||
|
||||
AbstractNode *FileModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx)
|
||||
{
|
||||
assert(evalctx == NULL);
|
||||
|
||||
delete context;
|
||||
context = new FileContext(*this, ctx);
|
||||
AbstractNode *node = new RootNode(inst);
|
||||
|
||||
try {
|
||||
context->initializeModule(*this);
|
||||
|
||||
// FIXME: Set document path to the path of the module
|
||||
std::vector<AbstractNode *> instantiatednodes = this->scope.instantiateChildren(context);
|
||||
node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end());
|
||||
}
|
||||
catch (EvaluationException &e) {
|
||||
PRINT(e.what());
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void FileModule::set_variable(const std::string name, Value value)
|
||||
{
|
||||
if (this->context) {
|
||||
this->context->set_variable(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
ValuePtr FileModule::lookup_variable(const std::string &name) const
|
||||
{
|
||||
if (!context) {
|
||||
return ValuePtr::undefined;
|
||||
}
|
||||
|
||||
return context->lookup_variable(name, true);
|
||||
}
|
||||
|
||||
void register_builtin_group()
|
||||
{
|
||||
Builtins::init("group", new GroupModule());
|
||||
}
|
||||
|
|
|
|||
147
src/module.h
147
src/module.h
|
|
@ -1,150 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "value.h"
|
||||
#include "typedefs.h"
|
||||
#include "localscope.h"
|
||||
#include "AST.h"
|
||||
#include "feature.h"
|
||||
#include "context.h"
|
||||
|
||||
class ModuleInstantiation
|
||||
{
|
||||
public:
|
||||
ModuleInstantiation(const std::string &name = "")
|
||||
: tag_root(false), tag_highlight(false), tag_background(false), modname(name) { }
|
||||
virtual ~ModuleInstantiation();
|
||||
|
||||
virtual std::string dump(const std::string &indent) const;
|
||||
class AbstractNode *evaluate(const class Context *ctx) const;
|
||||
std::vector<AbstractNode*> instantiateChildren(const Context *evalctx) const;
|
||||
|
||||
void setPath(const std::string &path) { this->modpath = path; }
|
||||
const std::string &path() const { return this->modpath; }
|
||||
std::string getAbsolutePath(const std::string &filename) const;
|
||||
|
||||
const std::string &name() const { return this->modname; }
|
||||
bool isBackground() const { return this->tag_background; }
|
||||
bool isHighlight() const { return this->tag_highlight; }
|
||||
bool isRoot() const { return this->tag_root; }
|
||||
|
||||
AssignmentList arguments;
|
||||
LocalScope scope;
|
||||
|
||||
bool tag_root;
|
||||
bool tag_highlight;
|
||||
bool tag_background;
|
||||
protected:
|
||||
std::string modname;
|
||||
std::string modpath;
|
||||
|
||||
friend class Module;
|
||||
};
|
||||
|
||||
class IfElseModuleInstantiation : public ModuleInstantiation {
|
||||
public:
|
||||
IfElseModuleInstantiation() : ModuleInstantiation("if") { }
|
||||
virtual ~IfElseModuleInstantiation();
|
||||
std::vector<AbstractNode*> instantiateElseChildren(const Context *evalctx) const;
|
||||
virtual std::string dump(const std::string &indent) const;
|
||||
|
||||
LocalScope else_scope;
|
||||
};
|
||||
|
||||
class AbstractModule
|
||||
{
|
||||
private:
|
||||
const Feature *feature;
|
||||
const Feature *feature;
|
||||
public:
|
||||
AbstractModule() : feature(NULL) {}
|
||||
AbstractModule(const Feature& feature) : feature(&feature) {}
|
||||
AbstractModule() : feature(NULL) {}
|
||||
AbstractModule(const Feature& feature) : feature(&feature) {}
|
||||
virtual ~AbstractModule();
|
||||
virtual bool is_experimental() const { return feature != NULL; }
|
||||
virtual bool is_enabled() const { return (feature == NULL) || feature->is_enabled(); }
|
||||
virtual class AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, class EvalContext *evalctx = NULL) const = 0;
|
||||
virtual bool is_experimental() const { return feature != NULL; }
|
||||
virtual bool is_enabled() const { return (feature == NULL) || feature->is_enabled(); }
|
||||
virtual class AbstractNode *instantiate(const class Context *ctx, const class ModuleInstantiation *inst, class EvalContext *evalctx = NULL) const = 0;
|
||||
virtual std::string dump(const std::string &indent, const std::string &name) const;
|
||||
virtual double lookup_double_variable_with_default(Context &c, std::string variable, double def) const;
|
||||
virtual std::string lookup_string_variable_with_default(Context &c, std::string variable, std::string def) const;
|
||||
};
|
||||
|
||||
class GroupModule : public AbstractModule
|
||||
{
|
||||
public:
|
||||
GroupModule() { }
|
||||
virtual ~GroupModule() { }
|
||||
virtual class AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, class EvalContext *evalctx = NULL) const;
|
||||
};
|
||||
|
||||
class Module : public AbstractModule
|
||||
{
|
||||
public:
|
||||
Module() { }
|
||||
Module(const Feature& feature) : AbstractModule(feature) { }
|
||||
virtual ~Module();
|
||||
|
||||
virtual void add_annotations(AnnotationList *annotations);
|
||||
virtual bool has_annotations() const;
|
||||
virtual const Annotation * annotation(const std::string &name) const;
|
||||
|
||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx = NULL) const;
|
||||
virtual std::string dump(const std::string &indent, const std::string &name) const;
|
||||
static const std::string& stack_element(int n) { return module_stack[n]; };
|
||||
static int stack_size() { return module_stack.size(); };
|
||||
|
||||
AssignmentList definition_arguments;
|
||||
|
||||
LocalScope scope;
|
||||
|
||||
protected:
|
||||
AnnotationMap annotations;
|
||||
|
||||
private:
|
||||
static std::deque<std::string> module_stack;
|
||||
};
|
||||
|
||||
// FIXME: A FileModule doesn't have definition arguments, so we shouldn't really
|
||||
// inherit from a Module
|
||||
class FileModule : public Module
|
||||
{
|
||||
public:
|
||||
FileModule() : context(NULL), is_handling_dependencies(false) {}
|
||||
virtual ~FileModule();
|
||||
|
||||
void setModulePath(const std::string &path) { this->path = path; }
|
||||
const std::string &modulePath() const { return this->path; }
|
||||
void registerUse(const std::string path);
|
||||
void registerInclude(const std::string &localpath, const std::string &fullpath);
|
||||
bool includesChanged() const;
|
||||
bool handleDependencies();
|
||||
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, EvalContext *evalctx = NULL);
|
||||
bool hasIncludes() const { return !this->includes.empty(); }
|
||||
bool usesLibraries() const { return !this->usedlibs.empty(); }
|
||||
bool isHandlingDependencies() const { return this->is_handling_dependencies; }
|
||||
void set_variable(const std::string name, Value value);
|
||||
ValuePtr lookup_variable(const std::string &name) const;
|
||||
|
||||
typedef std::unordered_set<std::string> ModuleContainer;
|
||||
ModuleContainer usedlibs;
|
||||
private:
|
||||
/** Reference to retain the context that was used in the last evaluation */
|
||||
class FileContext *context;
|
||||
struct IncludeFile {
|
||||
std::string filename;
|
||||
bool valid;
|
||||
time_t mtime;
|
||||
};
|
||||
|
||||
bool include_modified(const IncludeFile &inc) const;
|
||||
|
||||
typedef std::unordered_map<std::string, struct IncludeFile> IncludeContainer;
|
||||
IncludeContainer includes;
|
||||
bool is_handling_dependencies;
|
||||
std::string path;
|
||||
virtual double lookup_double_variable_with_default(Context &c, std::string variable, double def) const;
|
||||
virtual std::string lookup_string_variable_with_default(Context &c, std::string variable, std::string def) const;
|
||||
};
|
||||
|
|
|
|||
33
src/node.cc
33
src/node.cc
|
|
@ -26,8 +26,8 @@
|
|||
|
||||
#include "node.h"
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "progress.h"
|
||||
#include "visitor.h"
|
||||
#include "stl-utils.h"
|
||||
|
||||
#include <iostream>
|
||||
|
|
@ -46,37 +46,6 @@ AbstractNode::~AbstractNode()
|
|||
std::for_each(this->children.begin(), this->children.end(), del_fun<AbstractNode>());
|
||||
}
|
||||
|
||||
Response AbstractNode::accept(class State &state, Visitor &visitor) const
|
||||
{
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
|
||||
Response AbstractIntersectionNode::accept(class State &state, Visitor &visitor) const
|
||||
{
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
|
||||
Response AbstractPolyNode::accept(class State &state, Visitor &visitor) const
|
||||
{
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
|
||||
Response GroupNode::accept(class State &state, Visitor &visitor) const
|
||||
{
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
|
||||
Response RootNode::accept(class State &state, Visitor &visitor) const
|
||||
{
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
|
||||
|
||||
Response LeafNode::accept(class State &state, Visitor &visitor) const
|
||||
{
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
|
||||
std::string AbstractNode::toString() const
|
||||
{
|
||||
return this->name() + "()";
|
||||
|
|
|
|||
19
src/node.h
19
src/node.h
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "traverser.h"
|
||||
#include "BaseVisitable.h"
|
||||
|
||||
extern int progress_report_count;
|
||||
extern void (*progress_report_f)(const class AbstractNode*, void*, int);
|
||||
extern void *progress_report_vp;
|
||||
|
||||
void progress_report_prep(AbstractNode *root, void (*f)(const class AbstractNode *node, void *vp, int mark), void *vp);
|
||||
void progress_report_prep(class AbstractNode *root, void (*f)(const class AbstractNode *node, void *vp, int mark), void *vp);
|
||||
void progress_report_fin();
|
||||
|
||||
/*!
|
||||
|
|
@ -18,7 +18,7 @@ void progress_report_fin();
|
|||
scratch for each compile.
|
||||
|
||||
*/
|
||||
class AbstractNode
|
||||
class AbstractNode : public BaseVisitable
|
||||
{
|
||||
// FIXME: the idx_counter/idx is mostly (only?) for debugging.
|
||||
// We can hash on pointer value or smth. else.
|
||||
|
|
@ -26,9 +26,9 @@ class AbstractNode
|
|||
// use smth. else to display node identifier in CSG tree output?
|
||||
static size_t idx_counter; // Node instantiation index
|
||||
public:
|
||||
VISITABLE();
|
||||
AbstractNode(const class ModuleInstantiation *mi);
|
||||
virtual ~AbstractNode();
|
||||
virtual Response accept(class State &state, class Visitor &visitor) const;
|
||||
virtual std::string toString() const;
|
||||
/*! The 'OpenSCAD name' of this node, defaults to classname, but can be
|
||||
overloaded to provide specialization for e.g. CSG nodes, primitive nodes etc.
|
||||
|
|
@ -58,9 +58,9 @@ public:
|
|||
class AbstractIntersectionNode : public AbstractNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
AbstractIntersectionNode(const ModuleInstantiation *mi) : AbstractNode(mi) { };
|
||||
virtual ~AbstractIntersectionNode() { };
|
||||
virtual Response accept(class State &state, class Visitor &visitor) const;
|
||||
virtual std::string toString() const;
|
||||
virtual std::string name() const;
|
||||
};
|
||||
|
|
@ -68,9 +68,9 @@ public:
|
|||
class AbstractPolyNode : public AbstractNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
AbstractPolyNode(const ModuleInstantiation *mi) : AbstractNode(mi) { };
|
||||
virtual ~AbstractPolyNode() { };
|
||||
virtual Response accept(class State &state, class Visitor &visitor) const;
|
||||
|
||||
enum render_mode_e {
|
||||
RENDER_CGAL,
|
||||
|
|
@ -85,9 +85,9 @@ public:
|
|||
class GroupNode : public AbstractNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
GroupNode(const class ModuleInstantiation *mi) : AbstractNode(mi) { }
|
||||
virtual ~GroupNode() { }
|
||||
virtual Response accept(class State &state, class Visitor &visitor) const;
|
||||
virtual std::string name() const;
|
||||
};
|
||||
|
||||
|
|
@ -97,18 +97,19 @@ public:
|
|||
class RootNode : public GroupNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
|
||||
RootNode(const class ModuleInstantiation *mi) : GroupNode(mi) { }
|
||||
virtual ~RootNode() { }
|
||||
virtual Response accept(class State &state, class Visitor &visitor) const;
|
||||
virtual std::string name() const;
|
||||
};
|
||||
|
||||
class LeafNode : public AbstractPolyNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
LeafNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) { };
|
||||
virtual ~LeafNode() { };
|
||||
virtual Response accept(class State &state, class Visitor &visitor) const;
|
||||
virtual const class Geometry *createGeometry() const = 0;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "nodedumper.h"
|
||||
#include "state.h"
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@
|
|||
#include <string>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include "visitor.h"
|
||||
#include "NodeVisitor.h"
|
||||
#include "node.h"
|
||||
#include "nodecache.h"
|
||||
|
||||
class NodeDumper : public Visitor
|
||||
class NodeDumper : public NodeVisitor
|
||||
{
|
||||
public:
|
||||
/*! If idPrefix is true, we will output "n<id>:" in front of each node,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "offsetnode.h"
|
||||
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "evalcontext.h"
|
||||
#include "printutils.h"
|
||||
#include "fileutils.h"
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "node.h"
|
||||
#include "visitor.h"
|
||||
#include "value.h"
|
||||
#include "clipper-utils.h"
|
||||
|
||||
class OffsetNode : public AbstractPolyNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
OffsetNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi), fn(0), fs(0), fa(0), delta(1), miter_limit(1000000.0), join_type(ClipperLib::jtRound) { }
|
||||
virtual Response accept(class State &state, Visitor &visitor) const {
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
virtual std::string toString() const;
|
||||
virtual std::string name() const { return "offset"; }
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "openscad.h"
|
||||
#include "node.h"
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "modcontext.h"
|
||||
#include "value.h"
|
||||
#include "export.h"
|
||||
|
|
|
|||
271
src/parser.y
271
src/parser.y
|
|
@ -24,7 +24,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
//%expect 3 /* Expect 2 shift/reduce conflict for ifelse_statement - "dangling else problem" */
|
||||
%expect 2 /* Expect 2 shift/reduce conflict for ifelse_statement - "dangling else problem" */
|
||||
|
||||
%{
|
||||
|
||||
|
|
@ -34,8 +34,10 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "module.h"
|
||||
#include "FileModule.h"
|
||||
#include "UserModule.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "Assignment.h"
|
||||
#include "expression.h"
|
||||
#include "value.h"
|
||||
#include "function.h"
|
||||
|
|
@ -49,7 +51,8 @@ namespace fs = boost::filesystem;
|
|||
#include "boosty.h"
|
||||
|
||||
#define YYMAXDEPTH 20000
|
||||
|
||||
#define LOC(loc) Location(loc.first_line, loc.first_column, loc.last_line, loc.last_column)
|
||||
|
||||
int parser_error_pos = -1;
|
||||
|
||||
int parserlex(void);
|
||||
|
|
@ -60,7 +63,6 @@ fs::path sourcefile(void);
|
|||
int lexerlex_destroy(void);
|
||||
int lexerlex(void);
|
||||
|
||||
extern AssignmentList * parser(const char *text);
|
||||
std::stack<LocalScope *> scope_stack;
|
||||
FileModule *rootmodule;
|
||||
|
||||
|
|
@ -77,30 +79,29 @@ fs::path parser_sourcefile;
|
|||
double number;
|
||||
class Value *value;
|
||||
class Expression *expr;
|
||||
class Vector *vec;
|
||||
class ModuleInstantiation *inst;
|
||||
class IfElseModuleInstantiation *ifelse;
|
||||
Assignment *arg;
|
||||
class Assignment *arg;
|
||||
AssignmentList *args;
|
||||
const Annotation *annotation;
|
||||
AnnotationList *annotations;
|
||||
}
|
||||
|
||||
%locations
|
||||
%token TOK_ERROR
|
||||
|
||||
%token TOK_MODULE
|
||||
%token TOK_ANNOTATION
|
||||
%token COMMENT DCOMMENT
|
||||
%token TOK_FUNCTION
|
||||
%token TOK_IF
|
||||
%token TOK_ELSE
|
||||
%token TOK_FOR
|
||||
%token TOK_LET
|
||||
%token TOK_EACH
|
||||
|
||||
%token TOK_EACH
|
||||
|
||||
%token <text> TOK_ID
|
||||
%token <text> TOK_STRING
|
||||
%token <text> CTOK_STRING
|
||||
%token <text> TOK_USE
|
||||
%token <number> TOK_NUMBER
|
||||
|
||||
|
|
@ -126,7 +127,7 @@ fs::path parser_sourcefile;
|
|||
%left '.'
|
||||
|
||||
%type <expr> expr
|
||||
%type <expr> vector_expr
|
||||
%type <vec> vector_expr
|
||||
%type <expr> list_comprehension_elements
|
||||
%type <expr> list_comprehension_elements_p
|
||||
%type <expr> list_comprehension_elements_or_expr
|
||||
|
|
@ -139,19 +140,14 @@ fs::path parser_sourcefile;
|
|||
%type <args> arguments_call
|
||||
%type <args> arguments_decl
|
||||
|
||||
%type <arg> assignment
|
||||
%type <arg> argument_call
|
||||
%type <arg> argument_decl
|
||||
|
||||
%type <annotation> annotation
|
||||
%type <annotation> parameter
|
||||
%type <annotations> parameters
|
||||
%type <annotation> description
|
||||
%type <annotations> descriptions
|
||||
%type <annotations> annotations
|
||||
|
||||
%type <text> module_id
|
||||
|
||||
%type <arg> assignment
|
||||
%type <annotation> annotation
|
||||
%type <annotations> annotations
|
||||
|
||||
%debug
|
||||
|
||||
%%
|
||||
|
|
@ -188,40 +184,7 @@ annotation:
|
|||
free($2);
|
||||
}
|
||||
;
|
||||
|
||||
descriptions:
|
||||
description
|
||||
{
|
||||
$$ = new AnnotationList();
|
||||
$$->push_back(*$1);
|
||||
delete $1;
|
||||
}
|
||||
;
|
||||
description:
|
||||
COMMENT arguments_call
|
||||
{
|
||||
$$ = Annotation::create("Description", *$2);
|
||||
}
|
||||
;
|
||||
|
||||
parameters:
|
||||
parameter
|
||||
{
|
||||
$$ = new AnnotationList();
|
||||
$$->push_back(*$1);
|
||||
delete $1;
|
||||
}
|
||||
;
|
||||
|
||||
parameter:
|
||||
COMMENT CTOK_STRING
|
||||
{
|
||||
AssignmentList *assignments;
|
||||
assignments=parser($2);
|
||||
$$ = Annotation::create("Parameter",*assignments);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
statement:
|
||||
';'
|
||||
| '{' inner_input '}'
|
||||
|
|
@ -234,24 +197,9 @@ statement:
|
|||
{
|
||||
$2->add_annotations($1);
|
||||
}
|
||||
| assignment parameters
|
||||
{
|
||||
$1->add_annotations($2);
|
||||
}
|
||||
| descriptions assignment
|
||||
{
|
||||
$2->add_annotations($1);
|
||||
}
|
||||
| descriptions assignment parameters
|
||||
{
|
||||
$2->add_annotations($1);
|
||||
$2->add_annotations($3);
|
||||
}
|
||||
| COMMENT CTOK_STRING {}
|
||||
| DCOMMENT CTOK_STRING {}
|
||||
| TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')'
|
||||
{
|
||||
Module *newmodule = new Module();
|
||||
UserModule *newmodule = new UserModule(LOC(@$));
|
||||
newmodule->definition_arguments = *$4;
|
||||
scope_stack.top()->modules[$2] = newmodule;
|
||||
scope_stack.push(&newmodule->scope);
|
||||
|
|
@ -262,23 +210,9 @@ statement:
|
|||
{
|
||||
scope_stack.pop();
|
||||
}
|
||||
| annotations TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')'
|
||||
{
|
||||
Module *newmodule = new Module();
|
||||
newmodule->definition_arguments = *$5;
|
||||
newmodule->add_annotations($1);
|
||||
scope_stack.top()->modules[$3] = newmodule;
|
||||
scope_stack.push(&newmodule->scope);
|
||||
free($3);
|
||||
delete $5;
|
||||
}
|
||||
statement
|
||||
{
|
||||
scope_stack.pop();
|
||||
}
|
||||
| TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr
|
||||
{
|
||||
Function *func = Function::create($2, *$4, $8);
|
||||
UserFunction *func = UserFunction::create($2, *$4, shared_ptr<Expression>($8), LOC(@$));
|
||||
scope_stack.top()->functions[$2] = func;
|
||||
free($2);
|
||||
delete $4;
|
||||
|
|
@ -296,21 +230,18 @@ assignment:
|
|||
{
|
||||
bool found = false;
|
||||
for (auto& iter : scope_stack.top()->assignments) {
|
||||
if (iter.first == $1) {
|
||||
iter.second = shared_ptr<Expression>($3);
|
||||
if (iter.name == $1) {
|
||||
iter.expr = shared_ptr<Expression>($3);
|
||||
found = true;
|
||||
$$ = &iter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
scope_stack.top()->assignments.push_back(Assignment($1, shared_ptr<Expression>($3)));
|
||||
$$ = &scope_stack.top()->assignments.back();
|
||||
scope_stack.top()->assignments.push_back(Assignment($1, shared_ptr<Expression>($3),LOC(@$)));
|
||||
}
|
||||
free($1);
|
||||
$$ = &scope_stack.top()->assignments.back();
|
||||
}
|
||||
| COMMENT CTOK_STRING {}
|
||||
| DCOMMENT CTOK_STRING {}
|
||||
;
|
||||
|
||||
module_instantiation:
|
||||
|
|
@ -369,9 +300,7 @@ ifelse_statement:
|
|||
if_statement:
|
||||
TOK_IF '(' expr ')'
|
||||
{
|
||||
$<ifelse>$ = new IfElseModuleInstantiation();
|
||||
$<ifelse>$->arguments.push_back(Assignment("", shared_ptr<Expression>($3)));
|
||||
$<ifelse>$->setPath(boosty::stringy(parser_sourcefile.parent_path()));
|
||||
$<ifelse>$ = new IfElseModuleInstantiation(shared_ptr<Expression>($3), boosty::stringy(parser_sourcefile.parent_path()), LOC(@$));
|
||||
scope_stack.push(&$<ifelse>$->scope);
|
||||
}
|
||||
child_statement
|
||||
|
|
@ -407,17 +336,7 @@ module_id:
|
|||
single_module_instantiation:
|
||||
module_id '(' arguments_call ')'
|
||||
{
|
||||
$$ = new ModuleInstantiation($1);
|
||||
$$->arguments = *$3;
|
||||
$$->setPath(boosty::stringy(parser_sourcefile.parent_path()));
|
||||
free($1);
|
||||
delete $3;
|
||||
}
|
||||
|module_id '(' arguments_call ')' COMMENT CTOK_STRING
|
||||
{
|
||||
$$ = new ModuleInstantiation($1);
|
||||
$$->arguments = *$3;
|
||||
$$->setPath(boosty::stringy(parser_sourcefile.parent_path()));
|
||||
$$ = new ModuleInstantiation($1, *$3, boosty::stringy(parser_sourcefile.parent_path()), LOC(@$));
|
||||
free($1);
|
||||
delete $3;
|
||||
}
|
||||
|
|
@ -426,120 +345,107 @@ single_module_instantiation:
|
|||
expr:
|
||||
TOK_TRUE
|
||||
{
|
||||
$$ = new ExpressionConst(ValuePtr(true));
|
||||
$$ = new Literal(ValuePtr(true), LOC(@$));
|
||||
}
|
||||
| TOK_FALSE
|
||||
{
|
||||
$$ = new ExpressionConst(ValuePtr(false));
|
||||
$$ = new Literal(ValuePtr(false), LOC(@$));
|
||||
}
|
||||
| TOK_UNDEF
|
||||
{
|
||||
$$ = new ExpressionConst(ValuePtr::undefined);
|
||||
$$ = new Literal(ValuePtr::undefined, LOC(@$));
|
||||
}
|
||||
| TOK_ID
|
||||
{
|
||||
$$ = new ExpressionLookup($1);
|
||||
$$ = new Lookup($1, LOC(@$));
|
||||
free($1);
|
||||
}
|
||||
| expr '.' TOK_ID
|
||||
{
|
||||
$$ = new ExpressionMember($1, $3);
|
||||
free($3);
|
||||
$$ = new MemberLookup($1, $3, LOC(@$));
|
||||
free($3);
|
||||
}
|
||||
| TOK_STRING
|
||||
{
|
||||
$$ = new ExpressionConst(ValuePtr(std::string($1)));
|
||||
free($1);
|
||||
$$ = new Literal(ValuePtr(std::string($1)), LOC(@$));
|
||||
free($1);
|
||||
}
|
||||
| CTOK_STRING
|
||||
{
|
||||
$$ = new ExpressionConst(ValuePtr(std::string($1)));
|
||||
free($1);
|
||||
}
|
||||
| COMMENT CTOK_STRING {}
|
||||
| COMMENT CTOK_STRING expr {
|
||||
$$=$3;
|
||||
}
|
||||
| TOK_NUMBER
|
||||
{
|
||||
$$ = new ExpressionConst(ValuePtr($1));
|
||||
$$ = new Literal(ValuePtr($1), LOC(@$));
|
||||
}
|
||||
| TOK_LET '(' arguments_call ')' expr %prec LET
|
||||
{
|
||||
$$ = new ExpressionLet(*$3, $5);
|
||||
delete $3;
|
||||
$$ = new Let(*$3, $5, LOC(@$));
|
||||
delete $3;
|
||||
}
|
||||
| '[' expr ':' expr ']'
|
||||
{
|
||||
$$ = new ExpressionRange($2, $4);
|
||||
$$ = new Range($2, $4, LOC(@$));
|
||||
}
|
||||
| '[' expr ':' expr ':' expr ']'
|
||||
{
|
||||
$$ = new ExpressionRange($2, $4, $6);
|
||||
$$ = new Range($2, $4, $6, LOC(@$));
|
||||
}
|
||||
| '[' optional_commas ']'
|
||||
{
|
||||
$$ = new ExpressionConst(ValuePtr(Value::VectorType()));
|
||||
$$ = new Literal(ValuePtr(Value::VectorType()), LOC(@$));
|
||||
}
|
||||
| '[' vector_expr optional_commas expr']'
|
||||
| '[' vector_expr optional_commas ']'
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| '[' vector_expr optional_commas']'
|
||||
{
|
||||
$$ = $2;
|
||||
$$ = $2;
|
||||
}
|
||||
| expr '*' expr
|
||||
{
|
||||
$$ = new ExpressionMultiply($1, $3);
|
||||
$$ = new BinaryOp($1, BinaryOp::Op::Multiply, $3, LOC(@$));
|
||||
}
|
||||
| expr '/' expr
|
||||
{
|
||||
$$ = new ExpressionDivision($1, $3);
|
||||
$$ = new BinaryOp($1, BinaryOp::Op::Divide, $3, LOC(@$));
|
||||
}
|
||||
| expr '%' expr
|
||||
{
|
||||
$$ = new ExpressionModulo($1, $3);
|
||||
$$ = new BinaryOp($1, BinaryOp::Op::Modulo, $3, LOC(@$));
|
||||
}
|
||||
| expr '+' expr
|
||||
{
|
||||
$$ = new ExpressionPlus($1, $3);
|
||||
$$ = new BinaryOp($1, BinaryOp::Op::Plus, $3, LOC(@$));
|
||||
}
|
||||
| expr '-' expr
|
||||
{
|
||||
$$ = new ExpressionMinus($1, $3);
|
||||
$$ = new BinaryOp($1, BinaryOp::Op::Minus, $3, LOC(@$));
|
||||
}
|
||||
| expr '<' expr
|
||||
{
|
||||
$$ = new ExpressionLess($1, $3);
|
||||
$$ = new BinaryOp($1, BinaryOp::Op::Less, $3, LOC(@$));
|
||||
}
|
||||
| expr LE expr
|
||||
{
|
||||
$$ = new ExpressionLessOrEqual($1, $3);
|
||||
$$ = new BinaryOp($1, BinaryOp::Op::LessEqual, $3, LOC(@$));
|
||||
}
|
||||
| expr EQ expr
|
||||
{
|
||||
$$ = new ExpressionEqual($1, $3);
|
||||
$$ = new BinaryOp($1, BinaryOp::Op::Equal, $3, LOC(@$));
|
||||
}
|
||||
| expr NE expr
|
||||
{
|
||||
$$ = new ExpressionNotEqual($1, $3);
|
||||
$$ = new BinaryOp($1, BinaryOp::Op::NotEqual, $3, LOC(@$));
|
||||
}
|
||||
| expr GE expr
|
||||
{
|
||||
$$ = new ExpressionGreaterOrEqual($1, $3);
|
||||
$$ = new BinaryOp($1, BinaryOp::Op::GreaterEqual, $3, LOC(@$));
|
||||
}
|
||||
| expr '>' expr
|
||||
{
|
||||
$$ = new ExpressionGreater($1, $3);
|
||||
$$ = new BinaryOp($1, BinaryOp::Op::Greater, $3, LOC(@$));
|
||||
}
|
||||
| expr AND expr
|
||||
{
|
||||
$$ = new ExpressionLogicalAnd($1, $3);
|
||||
$$ = new BinaryOp($1, BinaryOp::Op::LogicalAnd, $3, LOC(@$));
|
||||
}
|
||||
| expr OR expr
|
||||
{
|
||||
$$ = new ExpressionLogicalOr($1, $3);
|
||||
$$ = new BinaryOp($1, BinaryOp::Op::LogicalOr, $3, LOC(@$));
|
||||
}
|
||||
| '+' expr
|
||||
{
|
||||
|
|
@ -547,29 +453,29 @@ expr:
|
|||
}
|
||||
| '-' expr
|
||||
{
|
||||
$$ = new ExpressionInvert($2);
|
||||
$$ = new UnaryOp(UnaryOp::Op::Negate, $2, LOC(@$));
|
||||
}
|
||||
| '!' expr
|
||||
{
|
||||
$$ = new ExpressionNot($2);
|
||||
$$ = new UnaryOp(UnaryOp::Op::Not, $2, LOC(@$));
|
||||
}
|
||||
| '(' expr ')'
|
||||
{
|
||||
$$ = $2;
|
||||
$$ = $2;
|
||||
}
|
||||
| expr '?' expr ':' expr
|
||||
{
|
||||
$$ = new ExpressionTernary($1, $3, $5);
|
||||
$$ = new TernaryOp($1, $3, $5, LOC(@$));
|
||||
}
|
||||
| expr '[' expr ']'
|
||||
{
|
||||
$$ = new ExpressionArrayLookup($1, $3);
|
||||
$$ = new ArrayLookup($1, $3, LOC(@$));
|
||||
}
|
||||
| TOK_ID '(' arguments_call ')'
|
||||
{
|
||||
$$ = new ExpressionFunctionCall($1, *$3);
|
||||
free($1);
|
||||
delete $3;
|
||||
$$ = new FunctionCall($1, *$3, LOC(@$));
|
||||
free($1);
|
||||
delete $3;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -578,12 +484,12 @@ list_comprehension_elements:
|
|||
be parsed as an expression) */
|
||||
TOK_LET '(' arguments_call ')' list_comprehension_elements_p
|
||||
{
|
||||
$$ = new ExpressionLcLet(*$3, $5);
|
||||
delete $3;
|
||||
$$ = new LcLet(*$3, $5, LOC(@$));
|
||||
delete $3;
|
||||
}
|
||||
| TOK_EACH list_comprehension_elements_or_expr
|
||||
{
|
||||
$$ = new ExpressionLcEach($2);
|
||||
$$ = new LcEach($2, LOC(@$));
|
||||
}
|
||||
| TOK_FOR '(' arguments_call ')' list_comprehension_elements_or_expr
|
||||
{
|
||||
|
|
@ -593,24 +499,24 @@ list_comprehension_elements:
|
|||
for (int i = $3->size()-1; i >= 0; i--) {
|
||||
AssignmentList arglist;
|
||||
arglist.push_back((*$3)[i]);
|
||||
Expression *e = new ExpressionLcFor(arglist, $$);
|
||||
Expression *e = new LcFor(arglist, $$, LOC(@$));
|
||||
$$ = e;
|
||||
}
|
||||
delete $3;
|
||||
}
|
||||
| TOK_FOR '(' arguments_call ';' expr ';' arguments_call ')' list_comprehension_elements_or_expr
|
||||
{
|
||||
$$ = new ExpressionLcForC(*$3, *$7, $5, $9);
|
||||
$$ = new LcForC(*$3, *$7, $5, $9, LOC(@$));
|
||||
delete $3;
|
||||
delete $7;
|
||||
}
|
||||
| TOK_IF '(' expr ')' list_comprehension_elements_or_expr
|
||||
{
|
||||
$$ = new ExpressionLcIf($3, $5, 0);
|
||||
$$ = new LcIf($3, $5, 0, LOC(@$));
|
||||
}
|
||||
| TOK_IF '(' expr ')' list_comprehension_elements_or_expr TOK_ELSE list_comprehension_elements_or_expr
|
||||
{
|
||||
$$ = new ExpressionLcIf($3, $5, $7);
|
||||
$$ = new LcIf($3, $5, $7, LOC(@$));
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -636,16 +542,18 @@ optional_commas:
|
|||
vector_expr:
|
||||
expr
|
||||
{
|
||||
$$ = new ExpressionVector($1);
|
||||
$$ = new Vector(LOC(@$));
|
||||
$$->push_back($1);
|
||||
}
|
||||
| list_comprehension_elements
|
||||
{
|
||||
$$ = new ExpressionVector($1);
|
||||
$$ = new Vector(LOC(@$));
|
||||
$$->push_back($1);
|
||||
}
|
||||
| vector_expr ',' optional_commas list_comprehension_elements_or_expr
|
||||
{
|
||||
$$ = $1;
|
||||
$$->children.push_back($4);
|
||||
$$ = $1;
|
||||
$$->push_back($4);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -660,37 +568,23 @@ arguments_decl:
|
|||
$$->push_back(*$1);
|
||||
delete $1;
|
||||
}
|
||||
| annotations argument_decl
|
||||
{
|
||||
$$ = new AssignmentList();
|
||||
$2->add_annotations($1);
|
||||
$$->push_back(*$2);
|
||||
delete $2;
|
||||
}
|
||||
| arguments_decl ',' optional_commas argument_decl
|
||||
{
|
||||
$$ = $1;
|
||||
$$->push_back(*$4);
|
||||
delete $4;
|
||||
}
|
||||
| arguments_decl ',' optional_commas annotations argument_decl
|
||||
{
|
||||
$$ = $1;
|
||||
$5->add_annotations($4);
|
||||
$$->push_back(*$5);
|
||||
delete $5;
|
||||
}
|
||||
;
|
||||
|
||||
argument_decl:
|
||||
TOK_ID
|
||||
{
|
||||
$$ = new Assignment($1);
|
||||
$$ = new Assignment($1, LOC(@$));
|
||||
free($1);
|
||||
}
|
||||
| TOK_ID '=' expr
|
||||
{
|
||||
$$ = new Assignment($1, shared_ptr<Expression>($3));
|
||||
$$ = new Assignment($1, shared_ptr<Expression>($3), LOC(@$));
|
||||
free($1);
|
||||
}
|
||||
;
|
||||
|
|
@ -717,11 +611,11 @@ arguments_call:
|
|||
argument_call:
|
||||
expr
|
||||
{
|
||||
$$ = new Assignment("", shared_ptr<Expression>($1));
|
||||
$$ = new Assignment("", shared_ptr<Expression>($1), LOC(@$));
|
||||
}
|
||||
| TOK_ID '=' expr
|
||||
{
|
||||
$$ = new Assignment($1, shared_ptr<Expression>($3));
|
||||
$$ = new Assignment($1, shared_ptr<Expression>($3), LOC(@$));
|
||||
free($1);
|
||||
}
|
||||
;
|
||||
|
|
@ -735,9 +629,9 @@ int parserlex(void)
|
|||
|
||||
void yyerror (char const *s)
|
||||
{
|
||||
// FIXME: We leak memory on parser errors...
|
||||
PRINTB("ERROR: Parser error in file %s, line %d: %s\n",
|
||||
sourcefile() % lexerget_lineno() % s);
|
||||
// FIXME: We leak memory on parser errors...
|
||||
PRINTB("ERROR: Parser error in file %s, line %d: %s\n",
|
||||
sourcefile() % lexerget_lineno() % s);
|
||||
}
|
||||
|
||||
FileModule *parse(const char *text, const fs::path &filename, int debug)
|
||||
|
|
@ -763,3 +657,4 @@ FileModule *parse(const char *text, const fs::path &filename, int debug)
|
|||
scope_stack.pop();
|
||||
return rootmodule;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
#include "Polygon2d.h"
|
||||
#include "builtin.h"
|
||||
#include "printutils.h"
|
||||
#include "visitor.h"
|
||||
#include "context.h"
|
||||
#include "calc.h"
|
||||
#include <sstream>
|
||||
|
|
@ -65,10 +64,8 @@ private:
|
|||
class PrimitiveNode : public LeafNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
PrimitiveNode(const ModuleInstantiation *mi, primitive_type_e type) : LeafNode(mi), type(type) { }
|
||||
virtual Response accept(class State &state, Visitor &visitor) const {
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
virtual std::string toString() const;
|
||||
virtual std::string name() const {
|
||||
switch (this->type) {
|
||||
|
|
|
|||
|
|
@ -26,10 +26,10 @@
|
|||
|
||||
#include "projectionnode.h"
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "evalcontext.h"
|
||||
#include "printutils.h"
|
||||
#include "builtin.h"
|
||||
#include "visitor.h"
|
||||
#include "polyset.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include "node.h"
|
||||
#include "visitor.h"
|
||||
#include <string>
|
||||
|
||||
class ProjectionNode : public AbstractPolyNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
ProjectionNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) {
|
||||
cut_mode = false;
|
||||
}
|
||||
virtual Response accept(class State &state, Visitor &visitor) const {
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
virtual std::string toString() const;
|
||||
virtual std::string name() const { return "projection"; }
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "rendernode.h"
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "evalcontext.h"
|
||||
#include "builtin.h"
|
||||
#include "polyset.h"
|
||||
|
|
|
|||
|
|
@ -1,16 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "node.h"
|
||||
#include "visitor.h"
|
||||
#include <string>
|
||||
|
||||
class RenderNode : public AbstractNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
RenderNode(const ModuleInstantiation *mi) : AbstractNode(mi), convexity(1) { }
|
||||
virtual Response accept(class State &state, Visitor &visitor) const {
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
virtual std::string toString() const;
|
||||
virtual std::string name() const { return "render"; }
|
||||
|
||||
|
|
|
|||
|
|
@ -26,12 +26,12 @@
|
|||
|
||||
#include "rotateextrudenode.h"
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "evalcontext.h"
|
||||
#include "printutils.h"
|
||||
#include "fileutils.h"
|
||||
#include "builtin.h"
|
||||
#include "polyset.h"
|
||||
#include "visitor.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <boost/assign/std/vector.hpp>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include "node.h"
|
||||
#include "visitor.h"
|
||||
#include "value.h"
|
||||
|
||||
class RotateExtrudeNode : public AbstractPolyNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
RotateExtrudeNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) {
|
||||
convexity = 0;
|
||||
fn = fs = fa = 0;
|
||||
origin_x = origin_y = scale = 0;
|
||||
angle = 360;
|
||||
}
|
||||
virtual Response accept(class State &state, Visitor &visitor) const {
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
virtual std::string toString() const;
|
||||
virtual std::string name() const { return "rotate_extrude"; }
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ Settings::~Settings()
|
|||
{
|
||||
}
|
||||
|
||||
void Settings::visit(Visitor& visitor)
|
||||
void Settings::visit(SettingsVisitor& visitor)
|
||||
{
|
||||
for (std::list<SettingsEntry *>::iterator it = entries.begin();it != entries.end();it++) {
|
||||
visitor.handle(*(*it));
|
||||
|
|
@ -109,11 +109,11 @@ void Settings::set(SettingsEntry& entry, const Value &val)
|
|||
entry._value = val;
|
||||
}
|
||||
|
||||
Visitor::Visitor()
|
||||
SettingsVisitor::SettingsVisitor()
|
||||
{
|
||||
}
|
||||
|
||||
Visitor::~Visitor()
|
||||
SettingsVisitor::~SettingsVisitor()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ public:
|
|||
|
||||
static Settings *inst(bool erase = false);
|
||||
|
||||
void visit(class Visitor& visitor);
|
||||
void visit(class SettingsVisitor& visitor);
|
||||
|
||||
const Value &defaultValue(const SettingsEntry& entry);
|
||||
const Value &get(const SettingsEntry& entry);
|
||||
|
|
@ -66,11 +66,11 @@ private:
|
|||
virtual ~Settings();
|
||||
};
|
||||
|
||||
class Visitor
|
||||
class SettingsVisitor
|
||||
{
|
||||
public:
|
||||
Visitor();
|
||||
virtual ~Visitor();
|
||||
SettingsVisitor();
|
||||
virtual ~SettingsVisitor();
|
||||
|
||||
virtual void handle(SettingsEntry& entry) const = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "node.h"
|
||||
#include "polyset.h"
|
||||
#include "evalcontext.h"
|
||||
|
|
@ -32,7 +33,6 @@
|
|||
#include "printutils.h"
|
||||
#include "fileutils.h"
|
||||
#include "handle_dep.h" // handle_dep()
|
||||
#include "visitor.h"
|
||||
#include "lodepng.h"
|
||||
|
||||
#include <sstream>
|
||||
|
|
@ -60,10 +60,8 @@ typedef std::unordered_map<std::pair<int,int>, double, boost::hash<std::pair<int
|
|||
class SurfaceNode : public LeafNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
SurfaceNode(const ModuleInstantiation *mi) : LeafNode(mi) { }
|
||||
virtual Response accept(class State &state, Visitor &visitor) const {
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
virtual std::string toString() const;
|
||||
virtual std::string name() const { return "surface"; }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "node.h"
|
||||
#include "visitor.h"
|
||||
#include "value.h"
|
||||
|
||||
#include "FreetypeRenderer.h"
|
||||
|
|
@ -11,12 +10,9 @@ class TextModule;
|
|||
class TextNode : public AbstractPolyNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
TextNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) {}
|
||||
|
||||
virtual Response accept(class State &state, Visitor &visitor) const {
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
|
||||
virtual std::string toString() const;
|
||||
virtual std::string name() const { return "text"; }
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
*/
|
||||
|
||||
#include "transformnode.h"
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "evalcontext.h"
|
||||
#include "polyset.h"
|
||||
#include "builtin.h"
|
||||
|
|
|
|||
|
|
@ -1,16 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "node.h"
|
||||
#include "visitor.h"
|
||||
#include "linalg.h"
|
||||
|
||||
class TransformNode : public AbstractNode
|
||||
{
|
||||
public:
|
||||
VISITABLE();
|
||||
TransformNode(const ModuleInstantiation *mi) : AbstractNode(mi) { }
|
||||
virtual Response accept(class State &state, Visitor &visitor) const {
|
||||
return visitor.visit(state, *this);
|
||||
}
|
||||
virtual std::string toString() const;
|
||||
virtual std::string name() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
enum Response {ContinueTraversal, AbortTraversal, PruneTraversal};
|
||||
|
||||
class Traverser
|
||||
{
|
||||
public:
|
||||
enum TraversalType {PREFIX, POSTFIX, PRE_AND_POSTFIX};
|
||||
|
||||
Traverser(class Visitor &visitor, const class AbstractNode &root, TraversalType travtype)
|
||||
: visitor(visitor), root(root), traversaltype(travtype) {
|
||||
}
|
||||
virtual ~Traverser() { }
|
||||
|
||||
void execute();
|
||||
// FIXME: reverse parameters
|
||||
Response traverse(const AbstractNode &node, const class State &state);
|
||||
private:
|
||||
|
||||
Visitor &visitor;
|
||||
const AbstractNode &root;
|
||||
TraversalType traversaltype;
|
||||
};
|
||||
5
testdata/scad/3D/issues/issue1671.scad
vendored
Normal file
5
testdata/scad/3D/issues/issue1671.scad
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
minkowski() {
|
||||
scale([0,0,1]) cube(1);
|
||||
scale([0,1,0]) cube(1);
|
||||
scale([1,0,0]) cube(1);
|
||||
}
|
||||
3
testdata/scad/3D/issues/issue1672.scad
vendored
Normal file
3
testdata/scad/3D/issues/issue1672.scad
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
hull() {
|
||||
scale([0,0,1]) cube(1);
|
||||
}
|
||||
|
|
@ -682,11 +682,18 @@ set(CORE_SOURCES
|
|||
../src/hash.cc
|
||||
../src/expr.cc
|
||||
../src/func.cc
|
||||
../src/function.cc
|
||||
../src/stackcheck.cc
|
||||
../src/localscope.cc
|
||||
../src/module.cc
|
||||
../src/FileModule.cc
|
||||
../src/UserModule.cc
|
||||
../src/GroupModule.cc
|
||||
../src/AST.cc
|
||||
../src/ModuleInstantiation.cc
|
||||
../src/ModuleCache.cc
|
||||
../src/node.cc
|
||||
../src/NodeVisitor.cc
|
||||
../src/context.cc
|
||||
../src/modcontext.cc
|
||||
../src/evalcontext.cc
|
||||
|
|
@ -759,7 +766,6 @@ set(CGAL_SOURCES
|
|||
|
||||
set(COMMON_SOURCES
|
||||
../src/nodedumper.cc
|
||||
../src/traverser.cc
|
||||
../src/GeometryCache.cc
|
||||
../src/clipper-utils.cc
|
||||
../src/Tree.cc
|
||||
|
|
@ -1168,7 +1174,8 @@ list(APPEND ECHO_FILES ${FUNCTION_FILES}
|
|||
${CMAKE_SOURCE_DIR}/../testdata/scad/issues/issue1472.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/empty-stl.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/issues/issue1516.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/issues/issue1528.scad)
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/issues/issue1528.scad
|
||||
)
|
||||
|
||||
list(APPEND DUMPTEST_FILES ${FEATURES_2D_FILES} ${FEATURES_3D_FILES} ${DEPRECATED_3D_FILES})
|
||||
list(APPEND DUMPTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/escape-test.scad
|
||||
|
|
@ -1380,7 +1387,8 @@ list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue13.scad
|
|||
${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1580-back-to-back2.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1580-import-back-to-back2.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1580-zero-area-triangle.scad
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1580-import-zero-area-triangle.scad)
|
||||
${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1580-import-zero-area-triangle.scad
|
||||
)
|
||||
|
||||
# We know that we cannot import weakly manifold files into CGAL, so to make tests easier
|
||||
# to manage, don't try. Once we improve import, we can reenable this
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@
|
|||
#include <string>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include "visitor.h"
|
||||
#include "state.h"
|
||||
#include "module.h" // FIXME: Temporarily for ModuleInstantiation
|
||||
#include "ModuleInstantiation.h"
|
||||
|
||||
#include "csgops.h"
|
||||
#include "transformnode.h"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef CSGTEXTRENDERER_H_
|
||||
#define CSGTEXTRENDERER_H_
|
||||
|
||||
#include "visitor.h"
|
||||
#include "NodeVisitor.h"
|
||||
#include "CSGTextCache.h"
|
||||
#include "enums.h"
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ using std::string;
|
|||
using std::map;
|
||||
using std::list;
|
||||
|
||||
class CSGTextRenderer : public Visitor
|
||||
class CSGTextRenderer : public NodeVisitor
|
||||
{
|
||||
public:
|
||||
CSGTextRenderer(CSGTextCache &cache) : cache(cache) {}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "parsersettings.h"
|
||||
#include "node.h"
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "modcontext.h"
|
||||
#include "value.h"
|
||||
#include "export.h"
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "parsersettings.h"
|
||||
#include "node.h"
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "modcontext.h"
|
||||
#include "value.h"
|
||||
#include "export.h"
|
||||
|
|
@ -58,8 +59,7 @@ std::string currentdir;
|
|||
void csgTree(CSGTextCache &cache, const AbstractNode &root)
|
||||
{
|
||||
CSGTextRenderer renderer(cache);
|
||||
Traverser render(renderer, root, Traverser::PRE_AND_POSTFIX);
|
||||
render.execute();
|
||||
renderer.traverse(root);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "parsersettings.h"
|
||||
#include "node.h"
|
||||
#include "module.h"
|
||||
#include "ModuleInstantiation.h"
|
||||
#include "modcontext.h"
|
||||
#include "value.h"
|
||||
#include "export.h"
|
||||
|
|
|
|||
BIN
tests/regression/cgalpngtest/issue1671-expected.png
Normal file
BIN
tests/regression/cgalpngtest/issue1671-expected.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
BIN
tests/regression/cgalpngtest/issue1672-expected.png
Normal file
BIN
tests/regression/cgalpngtest/issue1672-expected.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
BIN
tests/regression/monotonepngtest/issue1671-expected.png
Normal file
BIN
tests/regression/monotonepngtest/issue1671-expected.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
BIN
tests/regression/opencsgtest/issue1671-expected.png
Normal file
BIN
tests/regression/opencsgtest/issue1671-expected.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
BIN
tests/regression/opencsgtest/issue1672-expected.png
Normal file
BIN
tests/regression/opencsgtest/issue1672-expected.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
BIN
tests/regression/throwntogethertest/issue1671-expected.png
Normal file
BIN
tests/regression/throwntogethertest/issue1671-expected.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue