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.pngBinary files differ index 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.pngBinary files differ index 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.pngBinary files differ index 7f6374c..5cb1c4c 100644 --- a/tests/regression/throwntogethertest/ifelse-tests-expected.png +++ b/tests/regression/throwntogethertest/ifelse-tests-expected.png | 
