diff options
24 files changed, 354 insertions, 47 deletions
diff --git a/contrib/scad-mode.el b/contrib/scad-mode.el index 5961b08..68a47e6 100644 --- a/contrib/scad-mode.el +++ b/contrib/scad-mode.el @@ -66,7 +66,7 @@ "round" "ceil" "floor" "pow" "sqrt" "exp" "log" "ln" "str" - "lookup" "version" "version_num" + "lookup" "version" "version_num" "len" "search" "dxf_dim" "dxf_cross" ;;dxfdim.cc ) "SCAD functions." @@ -74,7 +74,7 @@ :group 'scad-font-lock) (defcustom scad-modules - '("child" "echo" "assign" "for" "intersection_for" "if" ;;control.cc + '("child" "echo" "assign" "for" "intersection_for" "if" "else" ;;control.cc "cube" "sphere" "cylinder" "polyhedron" "square" "circle" "polygon" ;;primitives.cc "scale" "rotate" "translate" "mirror" "multmatrix" ;;transform.cc "union" "difference" "intersection" ;;csgops.cc @@ -86,7 +86,7 @@ "import_stl" "import_off" "import_dxf" "import" ;;import.cc "group" ;;builtin.cc "projection" ;;projection.cc - "minkowski" "glide" "subdiv" "hull" ;;cgaladv.cc + "minkowski" "glide" "subdiv" "hull" "resize" ;;cgaladv.cc ) "SCAD modules." :type 'list diff --git a/src/dxfdim.cc b/src/dxfdim.cc index 66842d2..a241b87 100644 --- a/src/dxfdim.cc +++ b/src/dxfdim.cc @@ -160,9 +160,16 @@ Value builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx) } std::stringstream keystream; + fs::path filepath(filename); + uintmax_t filesize = -1; + time_t lastwritetime = -1; + if (fs::exists(filepath) && fs::is_regular_file(filepath)) { + filesize = fs::file_size(filepath); + lastwritetime = fs::last_write_time(filepath); + } keystream << filename << "|" << layername << "|" << xorigin << "|" << yorigin - << "|" << scale << "|" << fs::last_write_time(filename) - << "|" << fs::file_size(filename); + << "|" << scale << "|" << lastwritetime + << "|" << filesize; std::string key = keystream.str(); if (dxf_cross_cache.find(key) != dxf_cross_cache.end()) diff --git a/src/expr.cc b/src/expr.cc index 1381c24..2e069f0 100644 --- a/src/expr.cc +++ b/src/expr.cc @@ -172,23 +172,27 @@ std::string Expression::toString() const if (this->type == "*" || this->type == "/" || this->type == "%" || this->type == "+" || this->type == "-" || this->type == "<" || this->type == "<=" || this->type == "==" || - this->type == "!=" || this->type == ">=" || this->type == ">") { + this->type == "!=" || this->type == ">=" || this->type == ">" || + this->type == "&&" || this->type == "||") { stream << "(" << *this->children[0] << " " << this->type << " " << *this->children[1] << ")"; } else if (this->type == "?:") { - stream << "(" << *this->children[0] << " ? " << this->type << " : " << *this->children[1] << ")"; + stream << "(" << *this->children[0] << " ? " << *this->children[1] << " : " << *this->children[2] << ")"; } else if (this->type == "[]") { - stream << "(" << *this->children[0] << "[" << *this->children[1] << "])"; + stream << *this->children[0] << "[" << *this->children[1] << "]"; } else if (this->type == "I") { - stream << "(-" << *this->children[0] << ")"; + stream << "-" << *this->children[0]; + } + else if (this->type == "!") { + stream << "!" << *this->children[0]; } else if (this->type == "C") { stream << this->const_value; } else if (this->type == "R") { - stream << "[" << *this->children[0] << " : " << *this->children[1] << " : " << this->children[2] << "]"; + stream << "[" << *this->children[0] << " : " << *this->children[1] << " : " << *this->children[2] << "]"; } else if (this->type == "V") { stream << "["; @@ -202,7 +206,7 @@ std::string Expression::toString() const stream << this->var_name; } else if (this->type == "N") { - stream << "(" << *this->children[0] << "." << this->var_name << ")"; + stream << *this->children[0] << "." << this->var_name; } else if (this->type == "F") { stream << this->call_funcname << "("; diff --git a/src/module.cc b/src/module.cc index b9b23d8..046d0c4 100644 --- a/src/module.cc +++ b/src/module.cc @@ -102,16 +102,35 @@ std::string ModuleInstantiation::dump(const std::string &indent) const if (scope.numElements() == 0) { dump << ");\n"; } else if (scope.numElements() == 1) { - dump << ")\n"; - dump << scope.dump(indent + "\t"); + dump << ") "; + dump << scope.dump(""); } else { dump << ") {\n"; - scope.dump(indent + "\t"); + 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); diff --git a/src/module.h b/src/module.h index ad2a46c..682e65b 100644 --- a/src/module.h +++ b/src/module.h @@ -19,7 +19,7 @@ public: : tag_root(false), tag_highlight(false), tag_background(false), recursioncount(0), modname(name) { } virtual ~ModuleInstantiation(); - std::string dump(const std::string &indent) const; + 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; @@ -51,6 +51,7 @@ 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; }; diff --git a/testdata/scad/features/ifelse-tests.scad b/testdata/scad/features/ifelse-tests.scad index d8c777b..3c72d55 100644 --- a/testdata/scad/features/ifelse-tests.scad +++ b/testdata/scad/features/ifelse-tests.scad @@ -1,5 +1,11 @@ -if (true) cube(2, true); -else cylinder(r=1,h=2); +if (true) { + cube(2, true); + translate([-3,0,0]) cube(2, true); +} +else { + cylinder(r=1,h=2); + translate([-3,0,0]) cylinder(r=1,h=2); +} translate([3,0,0]) if (false) cylinder(r=1,h=2); diff --git a/testdata/scad/minimal/allexpressions.scad b/testdata/scad/minimal/allexpressions.scad new file mode 100644 index 0000000..f618c4b --- /dev/null +++ b/testdata/scad/minimal/allexpressions.scad @@ -0,0 +1,30 @@ +a = true; +b = false; +c = undef; +d = a; +e = $fn; +f1 = [1,,]; +f2 = [1,2,3]; +g = f2.x + f2.y + f2.z; +h1 = [2:5]; +h2 = [1:2:10]; +i = h2.begin - h2.step - h2.end; +j = "test"; +k = 1.23e-2; +l = a * b; +m = a / b; +n = a % b; +o = c < d; +p = c <= d; +q = c == d; +r = c != d; +s = c >= d; +t = c > d; +u = e && g; +v = e || g; +w = +i; +x = -i; +y = !i; +z = (j); +aa = k ? l : m; +bb = n[o]; diff --git a/testdata/scad/minimal/allfunctions.scad b/testdata/scad/minimal/allfunctions.scad index 2aebe54..b97f121 100644 --- a/testdata/scad/minimal/allfunctions.scad +++ b/testdata/scad/minimal/allfunctions.scad @@ -1,27 +1,28 @@ a = abs(); -a = sign(); -a = rands(); -a = min(); -a = max(); -a = sin(); -a = cos(); -a = asin(); -a = acos(); -a = tan(); -a = atan(); -a = atan2(); -a = round(); -a = ceil(); -a = floor(); -a = pow(); -a = sqrt(); -a = exp(); -a = log(); -a = ln(); -a = str(); -a = lookup(); -a = dxf_dim(); -a = dxf_cross(); -a = version(); -a = version_num(); -a = len(); +b = sign(); +c = rands(); +d = min(); +e = max(); +f = sin(); +g = cos(); +h = asin(); +i = acos(); +j = tan(); +k = atan(); +l = atan2(); +m = round(); +n = ceil(); +o = floor(); +p = pow(); +q = sqrt(); +r = exp(); +s = log(); +t = ln(); +u = str(); +v = lookup(); +w = dxf_dim(); +x = dxf_cross(); +y = version(); +z = version_num(); +aa = len(); +bb = search(); diff --git a/testdata/scad/minimal/allmodules.scad b/testdata/scad/minimal/allmodules.scad index 4395fd7..2e38d8f 100644 --- a/testdata/scad/minimal/allmodules.scad +++ b/testdata/scad/minimal/allmodules.scad @@ -2,12 +2,13 @@ minkowski(); glide(); subdiv(); hull(); +resize(); child(); echo(); assign(); for(); intersection_for(); -if(true) { } +if(false) { cube(); } else { sphere(); } union(); difference(); intersection(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d1ee312..2781124 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -531,6 +531,12 @@ add_executable(dumptest dumptest.cc) target_link_libraries(dumptest tests-nocgal ${TESTS-NOCGAL-LIBRARIES}) # +# moduledumptest +# +add_executable(moduledumptest moduledumptest.cc) +target_link_libraries(moduledumptest tests-nocgal ${TESTS-NOCGAL-LIBRARIES}) + +# # modulecachetest # add_executable(modulecachetest modulecachetest.cc) @@ -920,6 +926,10 @@ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake ${TMP}) add_cmdline_test(echotest SUFFIX txt FILES ${ECHO_FILES}) add_cmdline_test(dumptest SUFFIX txt FILES ${DUMPTEST_FILES}) +add_cmdline_test(moduledumptest SUFFIX txt FILES + ${CMAKE_SOURCE_DIR}/../testdata/scad/minimal/allmodules.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/minimal/allfunctions.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/minimal/allexpressions.scad) add_cmdline_test(csgtexttest SUFFIX txt FILES ${MINIMAL_FILES}) add_cmdline_test(csgtermtest SUFFIX txt FILES ${MINIMAL_FILES}) add_cmdline_test(cgalpngtest SUFFIX png FILES ${CGALPNGTEST_FILES}) diff --git a/tests/moduledumptest.cc b/tests/moduledumptest.cc new file mode 100644 index 0000000..5925d03 --- /dev/null +++ b/tests/moduledumptest.cc @@ -0,0 +1,118 @@ +/* + * 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 "tests-common.h" +#include "openscad.h" +#include "parsersettings.h" +#include "node.h" +#include "module.h" +#include "modcontext.h" +#include "value.h" +#include "export.h" +#include "builtin.h" +#include "Tree.h" + +#ifndef _MSC_VER +#include <getopt.h> +#endif +#include <assert.h> +#include <iostream> +#include <sstream> +#include <fstream> + +#include <boost/filesystem.hpp> +namespace fs = boost::filesystem; +#include "boosty.h" + +std::string commandline_commands; +std::string currentdir; + +using std::string; + +string dumptree(const Tree &tree, const AbstractNode &node) +{ + std::stringstream str; + const std::vector<AbstractNode*> &children = node.getChildren(); + for (std::vector<AbstractNode*>::const_iterator iter = children.begin(); iter != children.end(); iter++) { + str << tree.getString(**iter) << "\n"; + } + return str.str(); +} + +int main(int argc, char **argv) +{ +#ifdef _MSC_VER + _set_output_format(_TWO_DIGIT_EXPONENT); +#endif + if (argc != 3) { + fprintf(stderr, "Usage: %s <file.scad> <output.txt>\n", argv[0]); + exit(1); + } + + const char *filename = argv[1]; + const char *outfilename = argv[2]; + int rc = 0; + + Builtins::instance()->initialize(); + + fs::path original_path = fs::current_path(); + + currentdir = boosty::stringy(fs::current_path()); + + parser_init(boosty::stringy(fs::path(argv[0]).branch_path())); + add_librarydir(boosty::stringy(fs::path(argv[0]).branch_path() / "../libraries")); + + ModuleContext top_ctx; + top_ctx.registerBuiltin(); + + FileModule *root_module; + ModuleInstantiation root_inst("group"); + + root_module = parsefile(filename); + if (!root_module) { + exit(1); + } + + string dumpstdstr = root_module->dump("", ""); + + fs::current_path(original_path); + std::ofstream outfile; + outfile.open(outfilename); + if (!outfile.is_open()) { + fprintf(stderr, "Error: Unable to open output file %s\n", outfilename); + exit(1); + } + std::cout << "Opened " << outfilename << "\n"; + outfile << dumpstdstr << "\n"; + outfile.close(); + if (outfile.fail()) fprintf(stderr, "Failed to close file\n"); + + delete root_module; + + Builtins::instance(true); + + return rc; +} diff --git a/tests/regression/cgalpngtest/ifelse-tests-expected.png b/tests/regression/cgalpngtest/ifelse-tests-expected.png Binary files differindex fcda7bc..6680498 100644 --- a/tests/regression/cgalpngtest/ifelse-tests-expected.png +++ b/tests/regression/cgalpngtest/ifelse-tests-expected.png diff --git a/tests/regression/csgtermtest/allexpressions-expected.txt b/tests/regression/csgtermtest/allexpressions-expected.txt new file mode 100644 index 0000000..a40cf60 --- /dev/null +++ b/tests/regression/csgtermtest/allexpressions-expected.txt @@ -0,0 +1 @@ +No top-level CSG object diff --git a/tests/regression/csgtermtest/allmodules-expected.txt b/tests/regression/csgtermtest/allmodules-expected.txt index f544c01..b802c81 100644 --- a/tests/regression/csgtermtest/allmodules-expected.txt +++ b/tests/regression/csgtermtest/allmodules-expected.txt @@ -1 +1 @@ -((((((cube23 + sphere24) + cylinder25) + polyhedron26) + square27) + circle28) + polygon29) +(((((((sphere12 + cube25) + sphere26) + cylinder27) + polyhedron28) + square29) + circle30) + polygon31) diff --git a/tests/regression/csgtexttest/allexpressions-expected.txt b/tests/regression/csgtexttest/allexpressions-expected.txt new file mode 100644 index 0000000..331822f --- /dev/null +++ b/tests/regression/csgtexttest/allexpressions-expected.txt @@ -0,0 +1 @@ +group1 diff --git a/tests/regression/csgtexttest/allmodules-expected.txt b/tests/regression/csgtexttest/allmodules-expected.txt index 49171ba..95e0029 100644 --- a/tests/regression/csgtexttest/allmodules-expected.txt +++ b/tests/regression/csgtexttest/allmodules-expected.txt @@ -1 +1 @@ -group1(minkowski2+glide3+subdiv4+hull5+group6+group6+group6+intersection9+group6+union11+difference12+intersection9+linear_extrude+linear_extrude+rotate_extrude+rotate_extrude+import+import+import+import+group6+cube+sphere+cylinder+polyhedron+square+circle+polygon+projection+render31+surface+transform33+transform33+transform35+transform33+transform33+color38) +group1(minkowski2+glide3+subdiv4+hull5+resize6+group7+group7+group7+intersection10+group11(sphere)+union13+difference14+intersection10+linear_extrude+linear_extrude+rotate_extrude+rotate_extrude+import+import+import+import+group7+cube+sphere+cylinder+polyhedron+square+circle+polygon+projection+render33+surface+transform35+transform35+transform37+transform35+transform35+color40) diff --git a/tests/regression/dumptest/allexpressions-expected.txt b/tests/regression/dumptest/allexpressions-expected.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/regression/dumptest/allexpressions-expected.txt @@ -0,0 +1 @@ + diff --git a/tests/regression/dumptest/allmodules-expected.txt b/tests/regression/dumptest/allmodules-expected.txt index e6bd498..74bf191 100644 --- a/tests/regression/dumptest/allmodules-expected.txt +++ b/tests/regression/dumptest/allmodules-expected.txt @@ -2,11 +2,14 @@ glide(path = undef, convexity = 0); subdiv(level = 1, convexity = 0); hull(); + resize(newsize = [0,0,0], auto = [0,0,0]); group(); group(); group(); intersection(); - group(); + group() { + sphere($fn = 0, $fa = 12, $fs = 2, r = 1); + } union(); difference(); intersection(); diff --git a/tests/regression/dumptest/ifelse-tests-expected.txt b/tests/regression/dumptest/ifelse-tests-expected.txt index 1b60002..e2d3fce 100644 --- a/tests/regression/dumptest/ifelse-tests-expected.txt +++ b/tests/regression/dumptest/ifelse-tests-expected.txt @@ -1,5 +1,8 @@ group() { cube(size = [2, 2, 2], center = true); + multmatrix([[1, 0, 0, -3], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + cube(size = [2, 2, 2], center = true); + } } multmatrix([[1, 0, 0, 3], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { group() { diff --git a/tests/regression/moduledumptest/allexpressions-expected.txt b/tests/regression/moduledumptest/allexpressions-expected.txt new file mode 100644 index 0000000..6d9de40 --- /dev/null +++ b/tests/regression/moduledumptest/allexpressions-expected.txt @@ -0,0 +1,31 @@ +a = true; +b = false; +c = undef; +d = a; +e = $fn; +f1 = [1]; +f2 = [1, 2, 3]; +g = ((f2.x + f2.y) + f2.z); +h1 = [2 : 1 : 5]; +h2 = [1 : 2 : 10]; +i = ((h2.begin - h2.step) - h2.end); +j = "test"; +k = 0.0123; +l = (a * b); +m = (a / b); +n = (a % b); +o = (c < d); +p = (c <= d); +q = (c == d); +r = (c != d); +s = (c >= d); +t = (c > d); +u = (e && g); +v = (e || g); +w = i; +x = -i; +y = !i; +z = j; +aa = (k ? l : m); +bb = n[o]; + diff --git a/tests/regression/moduledumptest/allfunctions-expected.txt b/tests/regression/moduledumptest/allfunctions-expected.txt new file mode 100644 index 0000000..a8a0fea --- /dev/null +++ b/tests/regression/moduledumptest/allfunctions-expected.txt @@ -0,0 +1,29 @@ +a = abs(); +b = sign(); +c = rands(); +d = min(); +e = max(); +f = sin(); +g = cos(); +h = asin(); +i = acos(); +j = tan(); +k = atan(); +l = atan2(); +m = round(); +n = ceil(); +o = floor(); +p = pow(); +q = sqrt(); +r = exp(); +s = log(); +t = ln(); +u = str(); +v = lookup(); +w = dxf_dim(); +x = dxf_cross(); +y = version(); +z = version_num(); +aa = len(); +bb = search(); + diff --git a/tests/regression/moduledumptest/allmodules-expected.txt b/tests/regression/moduledumptest/allmodules-expected.txt new file mode 100644 index 0000000..0e3fc32 --- /dev/null +++ b/tests/regression/moduledumptest/allmodules-expected.txt @@ -0,0 +1,41 @@ +minkowski(); +glide(); +subdiv(); +hull(); +resize(); +child(); +echo(); +assign(); +for(); +intersection_for(); +if(false) cube(); +else sphere(); +union(); +difference(); +intersection(); +dxf_linear_extrude(); +linear_extrude(); +dxf_rotate_extrude(); +rotate_extrude(); +import(); +import_stl(); +import_off(); +import_dxf(); +group(); +cube(); +sphere(); +cylinder(); +polyhedron(); +square(); +circle(); +polygon(); +projection(); +render(); +surface(); +scale(); +rotate(); +mirror(); +translate(); +multmatrix(); +color(); + diff --git a/tests/regression/opencsgtest/ifelse-tests-expected.png b/tests/regression/opencsgtest/ifelse-tests-expected.png Binary files differindex 6dae4df..84e18e3 100644 --- a/tests/regression/opencsgtest/ifelse-tests-expected.png +++ b/tests/regression/opencsgtest/ifelse-tests-expected.png diff --git a/tests/regression/throwntogethertest/ifelse-tests-expected.png b/tests/regression/throwntogethertest/ifelse-tests-expected.png Binary files differindex 7f6374c..5cb1c4c 100644 --- a/tests/regression/throwntogethertest/ifelse-tests-expected.png +++ b/tests/regression/throwntogethertest/ifelse-tests-expected.png |