Dear developers,
We want to get the all AST nodes information of an OpenSCAD scripting file. To find the AST nodes of an OpenSCAD scripting file, we've integrated spdlog C++ logging library. We have put the logging statement in the source code of OpenSCAD, and we've gotten some information about the output when rendering an OpenSCAD scripting file. However, we have not gotten the expected information.
Could you please give us some hints about where should we instrument our statements in the source code to the all AST nodes of an OpenSCAD scripting file. We prefer to output the individual node in the spdlog file.
Thanks for you help.
Best regards,
Youbao
OpenSCAD can write the AST to disk using “openscad file.scad -o out.ast”.
This AST is written in OpenSCAD format. If you want another format, I would look into reimplementing AST::print() to fit your needs: https://github.com/openscad/openscad/blob/ce5039f8a9545ad5a8cf197b3ca11c0939bc67f1/src/core/AST.h#L50
-Marius
On Mar 27, 2025, at 12:31, Youbao Zhang via Discuss discuss@lists.openscad.org wrote:
Dear developers,
We want to get the all AST nodes information of an OpenSCAD scripting file. To find the AST nodes of an OpenSCAD scripting file, we've integrated spdlog C++ logging library. We have put the logging statement in the source code of OpenSCAD, and we've gotten some information about the output when rendering an OpenSCAD scripting file. However, we have not gotten the expected information.
Could you please give us some hints about where should we instrument our statements in the source code to the all AST nodes of an OpenSCAD scripting file. We prefer to output the individual node in the spdlog file.
Thanks for you help.
Best regards,
Youbao
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
Thank you for your help, Marius.
The command of “openscad file.scad -o out.ast” is just a dump of the original file.scad, which is almost the same with the original file.scad file. We need the all the node information of the file.scad. We would greatly appreciate it if you could help us achieve our goal through reimplementing AST::print(). Actually, we like the in-memory AST object, and want to manipulate the object in-memory.
For example, we have an OpenSCAD example like the following:
// Difference
difference() {
cube([10, 10, 10]);
sphere(7);
}
// Union
translate([15, 0, 0]) {
union() {
cube([10, 10, 10]);
sphere(7);
}
}
// Minkowski
translate([0, 15, 0]) {
minkowski() {
cube([5, 5, 5]);
sphere(3);
}
}
// Hull
translate([15, 15, 0]) {
hull() {
cube([5, 5, 5]);
translate([10, 10, 0]) sphere(3);
}
}
And we want to get the node information like the following show:
3DObject
├── difference
│ ├── cube
│ │ ├── dimensions: [10, 10, 10]
│ └── sphere
│ ├── radius: 7
├── translate
│ ├── offset: [15, 0, 0]
│ └── union
│ ├── cube
│ │ ├── dimensions: [10, 10, 10]
│ └── sphere
│ ├── radius: 7
├── translate
│ ├── offset: [0, 15, 0]
│ └── minkowski
│ ├── cube
│ │ ├── dimensions: [5, 5, 5]
│ └── sphere
│ ├── radius: 3
├── translate
│ ├── offset: [15, 15, 0]
│ └── hull
│ ├── cube
│ │ ├── dimensions: [5, 5, 5]
│ └── translate
│ ├── offset: [10, 10, 0]
│ └── sphere
│ ├── radius: 3
We want to do some translation (convertion) on the AST nodes, and then converting the AST nodes into source code file, such as Python file.
Best regards,
Youbao
-----Original Messages-----
From:"Marius Kintel via Discuss" discuss@lists.openscad.org
Sent Time:2025-03-28 00:58:17 (Friday)
To: "OpenSCAD general discussion Mailing-list" discuss@lists.openscad.org
Cc: zhangyoubao@siom.ac.cn, "Marius Kintel" marius@kintel.net
Subject: [OpenSCAD] Re: How to output the AST nodes of an OpenSCAD scripting file?
OpenSCAD can write the AST to disk using “openscad file.scad -o out.ast”.
This AST is written in OpenSCAD format. If you want another format, I would look into reimplementing AST::print() to fit your needs: https://github.com/openscad/openscad/blob/ce5039f8a9545ad5a8cf197b3ca11c0939bc67f1/src/core/AST.h#L50
-Marius
On Mar 27, 2025, at 12:31, Youbao Zhang via Discuss discuss@lists.openscad.org wrote:
Dear developers,
We want to get the all AST nodes information of an OpenSCAD scripting file. To find the AST nodes of an OpenSCAD scripting file, we've integrated spdlog C++ logging library. We have put the logging statement in the source code of OpenSCAD, and we've gotten some information about the output when rendering an OpenSCAD scripting file. However, we have not gotten the expected information.
Could you please give us some hints about where should we instrument our statements in the source code to the all AST nodes of an OpenSCAD scripting file. We prefer to output the individual node in the spdlog file.
Thanks for you help.
Best regards,
Youbao
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
If there exists some standard AST format, that would be a reasonable feature request.
However, this isn’t something us core developers will be able to contribute much time towards, so I’d suggest taking a stab at it yourself.
..or if you’re lucky, someone else reading along is able to assist.
Another option is to repackage the OpenSCAD parser as a separate library and write some API bindings for it. That’s also a fair bit of work, and not currently on our radar, but all of OpenSCAD is written in pretty standard C++, so it’s completely doable to move in that direction.
-Marius
On Mar 27, 2025, at 23:31, zhangyoubao@siom.ac.cn wrote:
Thank you for your help, Marius.
The command of “openscad file.scad -o out.ast” is just a dump of the original file.scad, which is almost the same with the original file.scad file. We need the all the node information of the file.scad. We would greatly appreciate it if you could help us achieve our goal through reimplementing AST::print(). Actually, we like the in-memory AST object, and want to manipulate the object in-memory.
For example, we have an OpenSCAD example like the following:
// Difference
difference() {
cube([10, 10, 10]);
sphere(7);
}
// Union
translate([15, 0, 0]) {
union() {
cube([10, 10, 10]);
sphere(7);
}
}
// Minkowski
translate([0, 15, 0]) {
minkowski() {
cube([5, 5, 5]);
sphere(3);
}
}
// Hull
translate([15, 15, 0]) {
hull() {
cube([5, 5, 5]);
translate([10, 10, 0]) sphere(3);
}
}
And we want to get the node information like the following show:
3DObject
├── difference
│ ├── cube
│ │ ├── dimensions: [10, 10, 10]
│ └── sphere
│ ├── radius: 7
├── translate
│ ├── offset: [15, 0, 0]
│ └── union
│ ├── cube
│ │ ├── dimensions: [10, 10, 10]
│ └── sphere
│ ├── radius: 7
├── translate
│ ├── offset: [0, 15, 0]
│ └── minkowski
│ ├── cube
│ │ ├── dimensions: [5, 5, 5]
│ └── sphere
│ ├── radius: 3
├── translate
│ ├── offset: [15, 15, 0]
│ └── hull
│ ├── cube
│ │ ├── dimensions: [5, 5, 5]
│ └── translate
│ ├── offset: [10, 10, 0]
│ └── sphere
│ ├── radius: 3
We want to do some translation (convertion) on the AST nodes, and then converting the AST nodes into source code file, such as Python file.
Best regards,
Youbao
-----Original Messages-----
From:"Marius Kintel via Discuss" discuss@lists.openscad.org
Sent Time:2025-03-28 00:58:17 (Friday)
To: "OpenSCAD general discussion Mailing-list" discuss@lists.openscad.org
Cc: zhangyoubao@siom.ac.cn, "Marius Kintel" marius@kintel.net
Subject: [OpenSCAD] Re: How to output the AST nodes of an OpenSCAD scripting file?
OpenSCAD can write the AST to disk using “openscad file.scad -o out.ast”.
This AST is written in OpenSCAD format. If you want another format, I would look into reimplementing AST::print() to fit your needs: https://github.com/openscad/openscad/blob/ce5039f8a9545ad5a8cf197b3ca11c0939bc67f1/src/core/AST.h#L50
-Marius
On Mar 27, 2025, at 12:31, Youbao Zhang via Discuss discuss@lists.openscad.org wrote:
Dear developers,
We want to get the all AST nodes information of an OpenSCAD scripting file. To find the AST nodes of an OpenSCAD scripting file, we've integrated spdlog C++ logging library. We have put the logging statement in the source code of OpenSCAD, and we've gotten some information about the output when rendering an OpenSCAD scripting file. However, we have not gotten the expected information.
Could you please give us some hints about where should we instrument our statements in the source code to the all AST nodes of an OpenSCAD scripting file. We prefer to output the individual node in the spdlog file.
Thanks for you help.
Best regards,
Youbao
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
On 3/27/2025 8:31 PM, Youbao Zhang via Discuss wrote:
The command of “openscad file.scad -o out.ast” is just a dump of the
original file.scad,
No. It's a dump of the AST... using OpenSCAD syntax. It is
reconstructed from the internal form of the AST. If you look carefully
you will see that all comments, whitespace, inclusion, et cetera have
been removed. Expressions are fully parenthesized. I don't happen to
know what else might change. But it is not a dump of the input
source; it is a dump of the AST in OpenSCAD syntax.
Any textual form of the AST will need to have a syntax, so why invent a
new one?
which is almost the same with the original file.scad file.
Yes, it often is.
We need the all the node information of the file.scad.
That's all that there is.
We would greatly appreciate it if you could help us achieve our goal
through reimplementing AST::print(). Actually, we like the in-memory
AST object, and want to manipulate the object in-memory.
You are of course welcome to work on such a thing, and I expect that
people will answer questions where they can, but you'd need to do the
work. Also, unless there's some general utility to your work, I would
expect that you'd need to maintain your own fork of the program
indefinitely.
For example, we have an OpenSCAD example like the following:
// Difference
difference() {
cube([10, 10, 10]);
sphere(7);
}
// Union
translate([15, 0, 0]) {
union() {
cube([10, 10, 10]);
sphere(7);
}
}
// Minkowski
translate([0, 15, 0]) {
minkowski() {
cube([5, 5, 5]);
sphere(3);
}
}
// Hull
translate([15, 15, 0]) {
hull() {
cube([5, 5, 5]);
translate([10, 10, 0]) sphere(3);
}
}
And we want to get the node information like the following show:
3DObject
├── difference
│ ├── cube
│ │ ├── dimensions: [10, 10, 10]
│ └── sphere
│ ├── radius: 7
├── translate
│ ├── offset: [15, 0, 0]
│ └── union
│ ├── cube
│ │ ├── dimensions: [10, 10, 10]
│ └── sphere
│ ├── radius: 7
├── translate
│ ├── offset: [0, 15, 0]
│ └── minkowski
│ ├── cube
│ │ ├── dimensions: [5, 5, 5]
│ └── sphere
│ ├── radius: 3
├── translate
│ ├── offset: [15, 15, 0]
│ └── hull
│ ├── cube
│ │ ├── dimensions: [5, 5, 5]
│ └── translate
│ ├── offset: [10, 10, 0]
│ └── sphere
│ ├── radius: 3
That's mostly just a rearrangement of the OpenSCAD-syntax AST. The only
thing that isn't readily derivable is the semantic meaning of the
arguments to the modules (e.g., that the first positional argument to
cube() is the dimensions), and that isn't in the AST. Only the cube()
module itself knows what its arguments mean.
It would be easier to work with if it always presented child nodes in
braces, whether or not they're needed, so that it's always exactly one
module invocation per line (except for close braces). That change would
be at these two locations:
https://github.com/openscad/openscad/blob/ce5039f8a9545ad5a8cf197b3ca11c0939bc67f1/src/core/ModuleInstantiation.cc#L26
https://github.com/openscad/openscad/blob/ce5039f8a9545ad5a8cf197b3ca11c0939bc67f1/src/core/ModuleInstantiation.cc#L45
I see that you're showing the top level as "3DObject". Remember that
the AST does not describe an object. It describes a program that
probably generates an object. You cannot directly determine what object
will be created from it without executing it.
For instance, this program produces either a cube or a sphere:
if (rands(0,1,1)[0] < 0.5) cube();
else sphere();
This program produces no object at all:
echo(2+2);
Note that in AST form the syntax has been standardized for you, but
the semantics are still assumed. If you want to generate an object,
you will need to execute the program as OpenSCAD itself would execute it.
If you want a description of the resulting object instead, you want CSG
(Constructive Solid Geometry) form. CSG is a textual dump of the CSG
tree that results from running the program, also presented in OpenSCAD
syntax (though a very limited subset). You can generate it the same way
you generate an AST dump, using "-o <name>.csg".
For your example, here's the output:
difference() {
cube(size = [10, 10, 10], center = false);
sphere($fn = 0, $fa = 12, $fs = 2, r = 7);
}
multmatrix([[1, 0, 0, 15], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
union() {
cube(size = [10, 10, 10], center = false);
sphere($fn = 0, $fa = 12, $fs = 2, r = 7);
}
}
multmatrix([[1, 0, 0, 0], [0, 1, 0, 15], [0, 0, 1, 0], [0, 0, 0, 1]]) {
minkowski(convexity = 0) {
cube(size = [5, 5, 5], center = false);
sphere($fn = 0, $fa = 12, $fs = 2, r = 3);
}
}
multmatrix([[1, 0, 0, 15], [0, 1, 0, 15], [0, 0, 1, 0], [0, 0, 0, 1]]) {
hull() {
cube(size = [5, 5, 5], center = false);
multmatrix([[1, 0, 0, 10], [0, 1, 0, 10], [0, 0, 1, 0], [0, 0, 0, 1]]) {
sphere($fn = 0, $fa = 12, $fs = 2, r = 3);
}
}
}
In CSG there are never any variables, expressions, control structures,
non-primitive modules, or functions, all transforms are turned into
matrix multiplies, and all arguments (including default ones) are
included explicitly.
In a simple case like your example, AST and CSG look kind of similar.
But they are very different.
For this program:
for (i=[1:3]) translate([i*10,0,0]) cube();
the AST is
for(i = [1 : 3]) translate([(i * 10), 0, 0]) cube();
but the CSG is:
group() {
multmatrix([[1, 0, 0, 10], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [1, 1, 1], center = false);
}
multmatrix([[1, 0, 0, 20], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [1, 1, 1], center = false);
}
multmatrix([[1, 0, 0, 30], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [1, 1, 1], center = false);
}
}
Dear Marius,
Thank you for your reply.
By the standard AST format, I think we could consider Python standard AST format.
I'd like to have a try by myself. I am here to get some suggestions about where is the best place to dive into the code for the AST feature.
I've started from openscad.cc, and then MainWindow.cc, and then other source files, and I think I am on the track, but maybe not on the absolutely right track. The following is the partial log from spdlog files.
[2025-03-28 11:32:14.651] [file_logger] [info] [openscad.cc:806] Logging from openscad.cc's main function......!
[2025-03-28 11:32:33.350] [file_logger] [info] [MainWindow.cc:2324] Render is clicked!
[2025-03-28 11:32:33.350] [file_logger] [info] [MainWindow.cc:2203] In MainWindow::prepareCompile(), Parsing design (AST generation)...
[2025-03-28 11:32:33.367] [file_logger] [info] [MainWindow.cc:2066] In MainWindow::parseTopLevelDocument()...
[2025-03-28 11:32:33.367] [file_logger] [info] [MainWindow.cc:2075] fulltext = // Difference
[2025-03-28 11:32:33.367] [file_logger] [info] [MainWindow.cc:2113] Just before this->rootFile = parse(this->parsedFile, fulltext, fname...
[2025-03-28 11:32:33.367] [file_logger] [info] [Tree.cc:75] In Tree::setRoot()......
[2025-03-28 11:32:33.367] [file_logger] [info] [Tree.cc:82] In Tree::setDocumentPath(), path =
[2025-03-28 11:32:33.378] [file_logger] [info] [MainWindow.cc:1349] Compiling design (CSG Tree generation)...
[2025-03-28 11:32:33.378] [file_logger] [info] [node.h:57] In resetIndexCounter(), idx_counter = 1
[2025-03-28 11:32:33.379] [file_logger] [info] [MainWindow.cc:1370] In if (this->absoluteRootNode) ......
[2025-03-28 11:32:33.379] [file_logger] [info] [node.cc:130] In find_root_tag(...) function.
[2025-03-28 11:32:33.379] [file_logger] [info] [Tree.cc:75] In Tree::setRoot()......
[2025-03-28 11:32:33.380] [file_logger] [info] [NodeVisitor.cc:13] node.getChildren().size() = 4
[2025-03-28 11:32:33.380] [file_logger] [info] [NodeVisitor.cc:13] node.getChildren().size() = 2
[2025-03-28 11:32:33.381] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = difference(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}multmatrix([[1,0,0,15],[0,1,0,0],[0,0,1,0],[0,0,0,1]]){union(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}}multmatrix([[1,0,0,0],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){minkowski(convexity=0){cube(size=[5,5,5],center=false);sphere($fn=0,$fa=12,$fs=2,r=3);}}multmatrix([[1,0,0,15],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){hull(){cube(size=[5,5,5],center=false);multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}}}
[2025-03-28 11:32:33.381] [file_logger] [info] [GeometryEvaluator.cc:79] Just before this->traverse(node) statement.
[2025-03-28 11:32:33.381] [file_logger] [info] [NodeVisitor.cc:13] node.getChildren().size() = 4
[2025-03-28 11:32:33.381] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = difference(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}multmatrix([[1,0,0,15],[0,1,0,0],[0,0,1,0],[0,0,0,1]]){union(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}}multmatrix([[1,0,0,0],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){minkowski(convexity=0){cube(size=[5,5,5],center=false);sphere($fn=0,$fa=12,$fs=2,r=3);}}multmatrix([[1,0,0,15],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){hull(){cube(size=[5,5,5],center=false);multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}}}
[2025-03-28 11:32:33.381] [file_logger] [info] [NodeVisitor.cc:13] node.getChildren().size() = 2
[2025-03-28 11:32:33.381] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = difference(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}
[2025-03-28 11:32:33.381] [file_logger] [info] [NodeVisitor.cc:13] node.getChildren().size() = 0
[2025-03-28 11:32:33.381] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = cube(size=[10,10,10],center=false);
[2025-03-28 11:32:33.381] [file_logger] [info] [NodeVisitor.cc:13] node.getChildren().size() = 0
[2025-03-28 11:32:33.381] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = sphere($fn=0,$fa=12,$fs=2,r=7);
[2025-03-28 11:32:33.382] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = difference(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}
[2025-03-28 11:32:33.382] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = cube(size=[10,10,10],center=false);
[2025-03-28 11:32:33.382] [file_logger] [info] [GeometryEvaluator.cc:329] The key is cube(size=[10,10,10],center=false);
[2025-03-28 11:32:33.382] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = sphere($fn=0,$fa=12,$fs=2,r=7);
[2025-03-28 11:32:33.382] [file_logger] [info] [GeometryEvaluator.cc:329] The key is sphere($fn=0,$fa=12,$fs=2,r=7);
[2025-03-28 11:32:33.492] [file_logger] [info] [NodeVisitor.cc:13] node.getChildren().size() = 1
[2025-03-28 11:32:33.492] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = multmatrix([[1,0,0,15],[0,1,0,0],[0,0,1,0],[0,0,0,1]]){union(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}}
[2025-03-28 11:32:33.492] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = union(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}
[2025-03-28 11:32:33.492] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = cube(size=[10,10,10],center=false);
[2025-03-28 11:32:33.492] [file_logger] [info] [GeometryEvaluator.cc:329] The key is cube(size=[10,10,10],center=false);
[2025-03-28 11:32:33.492] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = sphere($fn=0,$fa=12,$fs=2,r=7);
[2025-03-28 11:32:33.492] [file_logger] [info] [GeometryEvaluator.cc:329] The key is sphere($fn=0,$fa=12,$fs=2,r=7);
[2025-03-28 11:32:33.615] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = multmatrix([[1,0,0,15],[0,1,0,0],[0,0,1,0],[0,0,0,1]]){union(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}}
[2025-03-28 11:32:33.615] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = union(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}
[2025-03-28 11:32:33.615] [file_logger] [info] [GeometryEvaluator.cc:329] The key is union(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}
[2025-03-28 11:32:33.660] [file_logger] [info] [NodeVisitor.cc:13] node.getChildren().size() = 1
[2025-03-28 11:32:33.660] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = multmatrix([[1,0,0,0],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){minkowski(convexity=0){cube(size=[5,5,5],center=false);sphere($fn=0,$fa=12,$fs=2,r=3);}}
[2025-03-28 11:32:33.660] [file_logger] [info] [NodeVisitor.cc:13] node.getChildren().size() = 2
[2025-03-28 11:32:33.660] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = minkowski(convexity=0){cube(size=[5,5,5],center=false);sphere($fn=0,$fa=12,$fs=2,r=3);}
[2025-03-28 11:32:33.660] [file_logger] [info] [NodeVisitor.cc:13] node.getChildren().size() = 0
[2025-03-28 11:32:33.660] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = cube(size=[5,5,5],center=false);
[2025-03-28 11:32:33.660] [file_logger] [info] [NodeVisitor.cc:13] node.getChildren().size() = 0
[2025-03-28 11:32:33.660] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = sphere($fn=0,$fa=12,$fs=2,r=3);
[2025-03-28 11:32:33.660] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = minkowski(convexity=0){cube(size=[5,5,5],center=false);sphere($fn=0,$fa=12,$fs=2,r=3);}
[2025-03-28 11:32:33.660] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = cube(size=[5,5,5],center=false);
[2025-03-28 11:32:33.660] [file_logger] [info] [GeometryEvaluator.cc:329] The key is cube(size=[5,5,5],center=false);
[2025-03-28 11:32:33.660] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = sphere($fn=0,$fa=12,$fs=2,r=3);
[2025-03-28 11:32:33.660] [file_logger] [info] [GeometryEvaluator.cc:329] The key is sphere($fn=0,$fa=12,$fs=2,r=3);
[2025-03-28 11:32:33.680] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = multmatrix([[1,0,0,0],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){minkowski(convexity=0){cube(size=[5,5,5],center=false);sphere($fn=0,$fa=12,$fs=2,r=3);}}
[2025-03-28 11:32:33.680] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = minkowski(convexity=0){cube(size=[5,5,5],center=false);sphere($fn=0,$fa=12,$fs=2,r=3);}
[2025-03-28 11:32:33.680] [file_logger] [info] [GeometryEvaluator.cc:329] The key is minkowski(convexity=0){cube(size=[5,5,5],center=false);sphere($fn=0,$fa=12,$fs=2,r=3);}
[2025-03-28 11:32:33.681] [file_logger] [info] [NodeVisitor.cc:13] node.getChildren().size() = 1
[2025-03-28 11:32:33.681] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = multmatrix([[1,0,0,15],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){hull(){cube(size=[5,5,5],center=false);multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}}}
[2025-03-28 11:32:33.681] [file_logger] [info] [NodeVisitor.cc:13] node.getChildren().size() = 2
[2025-03-28 11:32:33.681] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = hull(){cube(size=[5,5,5],center=false);multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}}
[2025-03-28 11:32:33.681] [file_logger] [info] [NodeVisitor.cc:13] node.getChildren().size() = 0
[2025-03-28 11:32:33.681] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = cube(size=[5,5,5],center=false);
[2025-03-28 11:32:33.681] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = cube(size=[5,5,5],center=false);
[2025-03-28 11:32:33.681] [file_logger] [info] [NodeVisitor.cc:13] node.getChildren().size() = 1
[2025-03-28 11:32:33.681] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}
[2025-03-28 11:32:33.681] [file_logger] [info] [NodeVisitor.cc:13] node.getChildren().size() = 0
[2025-03-28 11:32:33.681] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = sphere($fn=0,$fa=12,$fs=2,r=3);
[2025-03-28 11:32:33.681] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = sphere($fn=0,$fa=12,$fs=2,r=3);
[2025-03-28 11:32:33.681] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}
[2025-03-28 11:32:33.681] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = sphere($fn=0,$fa=12,$fs=2,r=3);
[2025-03-28 11:32:33.681] [file_logger] [info] [GeometryEvaluator.cc:329] The key is sphere($fn=0,$fa=12,$fs=2,r=3);
[2025-03-28 11:32:33.681] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = hull(){cube(size=[5,5,5],center=false);multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}}
[2025-03-28 11:32:33.681] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = cube(size=[5,5,5],center=false);
[2025-03-28 11:32:33.681] [file_logger] [info] [GeometryEvaluator.cc:329] The key is cube(size=[5,5,5],center=false);
[2025-03-28 11:32:33.681] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}
[2025-03-28 11:32:33.681] [file_logger] [info] [GeometryEvaluator.cc:329] The key is multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}
[2025-03-28 11:32:33.683] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = multmatrix([[1,0,0,15],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){hull(){cube(size=[5,5,5],center=false);multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}}}
[2025-03-28 11:32:33.683] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = hull(){cube(size=[5,5,5],center=false);multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}}
[2025-03-28 11:32:33.683] [file_logger] [info] [GeometryEvaluator.cc:329] The key is hull(){cube(size=[5,5,5],center=false);multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}}
[2025-03-28 11:32:33.683] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = difference(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}multmatrix([[1,0,0,15],[0,1,0,0],[0,0,1,0],[0,0,0,1]]){union(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}}multmatrix([[1,0,0,0],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){minkowski(convexity=0){cube(size=[5,5,5],center=false);sphere($fn=0,$fa=12,$fs=2,r=3);}}multmatrix([[1,0,0,15],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){hull(){cube(size=[5,5,5],center=false);multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}}}
[2025-03-28 11:32:33.683] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = difference(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}
[2025-03-28 11:32:33.683] [file_logger] [info] [GeometryEvaluator.cc:329] The key is difference(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}
[2025-03-28 11:32:33.683] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = multmatrix([[1,0,0,15],[0,1,0,0],[0,0,1,0],[0,0,0,1]]){union(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}}
[2025-03-28 11:32:33.683] [file_logger] [info] [GeometryEvaluator.cc:329] The key is multmatrix([[1,0,0,15],[0,1,0,0],[0,0,1,0],[0,0,0,1]]){union(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}}
[2025-03-28 11:32:33.684] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = multmatrix([[1,0,0,0],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){minkowski(convexity=0){cube(size=[5,5,5],center=false);sphere($fn=0,$fa=12,$fs=2,r=3);}}
[2025-03-28 11:32:33.684] [file_logger] [info] [GeometryEvaluator.cc:329] The key is multmatrix([[1,0,0,0],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){minkowski(convexity=0){cube(size=[5,5,5],center=false);sphere($fn=0,$fa=12,$fs=2,r=3);}}
[2025-03-28 11:32:33.684] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = multmatrix([[1,0,0,15],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){hull(){cube(size=[5,5,5],center=false);multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}}}
[2025-03-28 11:32:33.684] [file_logger] [info] [GeometryEvaluator.cc:329] The key is multmatrix([[1,0,0,15],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){hull(){cube(size=[5,5,5],center=false);multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}}}
[2025-03-28 11:32:33.862] [file_logger] [info] [Tree.cc:65] In Tree::getIdString(), nodecache[node] = difference(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}multmatrix([[1,0,0,15],[0,1,0,0],[0,0,1,0],[0,0,0,1]]){union(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}}multmatrix([[1,0,0,0],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){minkowski(convexity=0){cube(size=[5,5,5],center=false);sphere($fn=0,$fa=12,$fs=2,r=3);}}multmatrix([[1,0,0,15],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){hull(){cube(size=[5,5,5],center=false);multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}}}
[2025-03-28 11:32:33.862] [file_logger] [info] [GeometryEvaluator.cc:329] The key is difference(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}multmatrix([[1,0,0,15],[0,1,0,0],[0,0,1,0],[0,0,0,1]]){union(){cube(size=[10,10,10],center=false);sphere($fn=0,$fa=12,$fs=2,r=7);}}multmatrix([[1,0,0,0],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){minkowski(convexity=0){cube(size=[5,5,5],center=false);sphere($fn=0,$fa=12,$fs=2,r=3);}}multmatrix([[1,0,0,15],[0,1,0,15],[0,0,1,0],[0,0,0,1]]){hull(){cube(size=[5,5,5],center=false);multmatrix([[1,0,0,10],[0,1,0,10],[0,0,1,0],[0,0,0,1]]){sphere($fn=0,$fa=12,$fs=2,r=3);}}}
Best regards,
Youbao
-----Original Messages-----
From:"Marius Kintel via Discuss" discuss@lists.openscad.org
Sent Time:2025-03-28 13:02:46 (Friday)
To: zhangyoubao@siom.ac.cn
Cc: "OpenSCAD general discussion Mailing-list" discuss@lists.openscad.org, "Marius Kintel" marius@kintel.net
Subject: [OpenSCAD] Re: How to output the AST nodes of an OpenSCAD scripting file?
If there exists some standard AST format, that would be a reasonable feature request.
However, this isn’t something us core developers will be able to contribute much time towards, so I’d suggest taking a stab at it yourself.
..or if you’re lucky, someone else reading along is able to assist.
Another option is to repackage the OpenSCAD parser as a separate library and write some API bindings for it. That’s also a fair bit of work, and not currently on our radar, but all of OpenSCAD is written in pretty standard C++, so it’s completely doable to move in that direction.
-Marius
On Mar 27, 2025, at 23:31, zhangyoubao@siom.ac.cn wrote:
Thank you for your help, Marius.
The command of “openscad file.scad -o out.ast” is just a dump of the original file.scad, which is almost the same with the original file.scad file. We need the all the node information of the file.scad. We would greatly appreciate it if you could help us achieve our goal through reimplementing AST::print(). Actually, we like the in-memory AST object, and want to manipulate the object in-memory.
For example, we have an OpenSCAD example like the following:
// Difference
difference() {
cube([10, 10, 10]);
sphere(7);
}
// Union
translate([15, 0, 0]) {
union() {
cube([10, 10, 10]);
sphere(7);
}
}
// Minkowski
translate([0, 15, 0]) {
minkowski() {
cube([5, 5, 5]);
sphere(3);
}
}
// Hull
translate([15, 15, 0]) {
hull() {
cube([5, 5, 5]);
translate([10, 10, 0]) sphere(3);
}
}
And we want to get the node information like the following show:
3DObject
├── difference
│ ├── cube
│ │ ├── dimensions: [10, 10, 10]
│ └── sphere
│ ├── radius: 7
├── translate
│ ├── offset: [15, 0, 0]
│ └── union
│ ├── cube
│ │ ├── dimensions: [10, 10, 10]
│ └── sphere
│ ├── radius: 7
├── translate
│ ├── offset: [0, 15, 0]
│ └── minkowski
│ ├── cube
│ │ ├── dimensions: [5, 5, 5]
│ └── sphere
│ ├── radius: 3
├── translate
│ ├── offset: [15, 15, 0]
│ └── hull
│ ├── cube
│ │ ├── dimensions: [5, 5, 5]
│ └── translate
│ ├── offset: [10, 10, 0]
│ └── sphere
│ ├── radius: 3
We want to do some translation (convertion) on the AST nodes, and then converting the AST nodes into source code file, such as Python file.
Best regards,
Youbao
-----Original Messages-----
From:"Marius Kintel via Discuss" discuss@lists.openscad.org
Sent Time:2025-03-28 00:58:17 (Friday)
To: "OpenSCAD general discussion Mailing-list" discuss@lists.openscad.org
Cc: zhangyoubao@siom.ac.cn, "Marius Kintel" marius@kintel.net
Subject: [OpenSCAD] Re: How to output the AST nodes of an OpenSCAD scripting file?
OpenSCAD can write the AST to disk using “openscad file.scad -o out.ast”.
This AST is written in OpenSCAD format. If you want another format, I would look into reimplementing AST::print() to fit your needs: https://github.com/openscad/openscad/blob/ce5039f8a9545ad5a8cf197b3ca11c0939bc67f1/src/core/AST.h#L50
-Marius
On Mar 27, 2025, at 12:31, Youbao Zhang via Discuss discuss@lists.openscad.org wrote:
Dear developers,
We want to get the all AST nodes information of an OpenSCAD scripting file. To find the AST nodes of an OpenSCAD scripting file, we've integrated spdlog C++ logging library. We have put the logging statement in the source code of OpenSCAD, and we've gotten some information about the output when rendering an OpenSCAD scripting file. However, we have not gotten the expected information.
Could you please give us some hints about where should we instrument our statements in the source code to the all AST nodes of an OpenSCAD scripting file. We prefer to output the individual node in the spdlog file.
Thanks for you help.
Best regards,
Youbao
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
On 3/28/2025 12:06 AM, Youbao Zhang via Discuss wrote:
I'd like to have a try by myself. I am here to get some suggestions
about where is the best place to dive into the code for the AST feature.
src/core
parser.y is the parser, generates the AST.
AST.h defines ASTNode. Its subclasses are the nodes in the AST.
ASTNode::print() is the function that emits an AST node in the AST dump,
implemented in each of the subclasses.
Dear Jordan, Marius,
Thank you very much for your help. Now, we could get all the AST nodes information in the function of NodeVisitor::traverse(...).
We still have two questions about the AST nodes:
Best regards,
Youbao
The result AST nodes:
root()
difference()
cube(size = [10, 10, 10], center = false)
sphere($fn = 0, $fa = 12, $fs = 2, r = 7)
translate multmatrix([[1, 0, 0, 15], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
union()
cube(size = [10, 10, 10], center = false)
sphere($fn = 0, $fa = 12, $fs = 2, r = 7)
translate multmatrix([[1, 0, 0, 0], [0, 1, 0, 15], [0, 0, 1, 0], [0, 0, 0, 1]])
minkowski(convexity = 0)
cube(size = [5, 5, 5], center = false)
sphere($fn = 0, $fa = 12, $fs = 2, r = 3)
translate multmatrix([[1, 0, 0, 15], [0, 1, 0, 15], [0, 0, 1, 0], [0, 0, 0, 1]])
hull()
cube(size = [5, 5, 5], center = false)
translate multmatrix([[1, 0, 0, 10], [0, 1, 0, 10], [0, 0, 1, 0], [0, 0, 0, 1]])
sphere($fn = 0, $fa = 12, $fs = 2, r = 3)
difference()
module mymodule
translate multmatrix([[1, 0, 0, 10], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
cube(size = [5, 5, 5], center = false)
rotate multmatrix([[1, 0, 0, 0], [0, 0.707107, -0.707107, 0], [0, 0.707107, 0.707107, 0], [0, 0, 0, 1]])
sphere($fn = 0, $fa = 12, $fs = 2, r = 10)
cylinder($fn = 0, $fa = 12, $fs = 2, h = 20, r1 = 5, r2 = 5, center = false)
The OpenSCAD script souce code:
// Difference
difference() {
cube([10, 10, 10]);
sphere(7);
}
// Union
translate([15, 0, 0]) {
union() {
cube([10, 10, 10]);
sphere(7);
}
}
// Minkowski
translate([0, 15, 0]) {
minkowski() {
cube([5, 5, 5]);
sphere(3);
}
}
// Hull
translate([15, 15, 0]) {
hull() {
cube([5, 5, 5]);
translate([10, 10, 0]) sphere(3);
}
}
module mymodule() {
translate([10, 0, 0]) cube([5, 5, 5]);
rotate([45, 0, 0]) sphere(10);
}
difference() {
mymodule();
cylinder(h = 20, r = 5);
}
-----Original Messages-----
From:"Jordan Brown via Discuss" discuss@lists.openscad.org
Sent Time:2025-03-28 17:45:39 (Friday)
To: "OpenSCAD general discussion Mailing-list" discuss@lists.openscad.org
Cc: zhangyoubao@siom.ac.cn, "Jordan Brown" openscad@jordan.maileater.net
Subject: [OpenSCAD] Re: How to output the AST nodes of an OpenSCAD scripting file?
On 3/28/2025 12:06 AM, Youbao Zhang via Discuss wrote:
I'd like to have a try by myself. I am here to get some suggestions about where is the best place to dive into the code for the AST feature.
src/core
parser.y is the parser, generates the AST.
AST.h defines ASTNode. Its subclasses are the nodes in the AST.
ASTNode::print() is the function that emits an AST node in the AST dump, implemented in each of the subclasses.
On 3/29/2025 2:15 AM, zhangyoubao@siom.ac.cn wrote:
Thank you very much for your help. Now, we could get all the AST nodes
information in the function of NodeVisitor::traverse(...).
Just to be clear, what you're looking at is a CSG dump, not an AST
dump. It's a dump of the generated geometry, not a dump of the program
that generates it. That makes it a lot easier to process, but of
course it doesn't have the same flexibility.
You've probably looked at the definition of AbstractNode more recently
than I have :-)
I don't see any level stored. I doubt that OpenSCAD would have any use
for it in its own processing. For a CSG dump I think it just
recursively walks the tree, and increments the indent whenever it descends.
You could certainly modify it to retain the original parameters
(probably through creating subclasses of TransformNode, each of which
had the right members), but it wouldn't be useful for OpenSCAD's core
mission. Including those in a CSG dump would actually make CSG dumps
harder to process, because the consumer would have to know about all of
the possible transforms, not just about multmatrix.
What are you really trying to accomplish? I know you've talked about
emitting Python, but for what purpose?
Dear Jordan,
Thank you very much for your help.
What are you really trying to accomplish? I know you've talked about emitting Python, but for what purpose?
We want to convert OpenSCAD scripts into CadQuery Python script files. Previously, we initiated a discussion titled "About Automatically Translating OpenSCAD Scripting Code into CadQuery Scripting Code (Python Code)." At that time, you also provided a suggestion: "Implementing the lexical analysis and the parser, or extracting the AST from OpenSCAD somehow, plus obvious implementations of primitives, will get you a modest fraction of OpenSCAD programs. Driving that fraction up will take a lot more."
Just to be clear, what you're looking at is a CSG dump, not an AST dump. It's a dump of the generated geometry, not a dump of the program that generates it. That makes it a lot easier to process, but of course it doesn't have the same flexibility.
Yes, you are right. It is a CSG dump, not an AST dump. We have now pinpointed the code for parsing *.scad files in MainWindow.cc under MainWindow::parseTopLevelDocument() with the following statement:
this->rootFile = parse(this->parsedFile, fulltext, fname, fname, false) ? this->parsedFile : nullptr;
The function Parameters Parameters::parse(...) reads quite cryptically. I think it might be possible to extract the actual AST node information from this function, but it seems to require a deeper understanding of the code. Is it feasible to easily obtain information about AST nodes from the existing program?
We still prefer to work on AST nodes for the code translation.
BTW, we could get the node-level information of the CSG dump in the souce code. The seconde column shows the node-level information.
0 0root()
1 1 difference()
2 2 cube(size = [10, 10, 10], center = false)
3 2 sphere($fn = 0, $fa = 12, $fs = 2, r = 7)
4 1 translate multmatrix([[1, 0, 0, 15], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
5 2 union()
6 3 cube(size = [10, 10, 10], center = false)
7 3 sphere($fn = 0, $fa = 12, $fs = 2, r = 7)
8 1 translate multmatrix([[1, 0, 0, 0], [0, 1, 0, 15], [0, 0, 1, 0], [0, 0, 0, 1]])
9 2 minkowski(convexity = 0)
10 3 cube(size = [5, 5, 5], center = false)
11 3 sphere($fn = 0, $fa = 12, $fs = 2, r = 3)
12 1 translate multmatrix([[1, 0, 0, 15], [0, 1, 0, 15], [0, 0, 1, 0], [0, 0, 0, 1]])
13 2 hull()
14 3 cube(size = [5, 5, 5], center = false)
15 3 translate multmatrix([[1, 0, 0, 10], [0, 1, 0, 10], [0, 0, 1, 0], [0, 0, 0, 1]])
16 4 sphere($fn = 0, $fa = 12, $fs = 2, r = 3)
17 1 difference()
18 2 module mymodule
19 3 translate multmatrix([[1, 0, 0, 10], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
20 4 cube(size = [5, 5, 5], center = false)
21 3 rotate multmatrix([[1, 0, 0, 0], [0, 0.707107, -0.707107, 0], [0, 0.707107, 0.707107, 0], [0, 0, 0, 1]])
22 4 sphere($fn = 0, $fa = 12, $fs = 2, r = 10)
23 2cylinder($fn = 0, $fa = 12, $fs = 2, h = 20, r1 = 5, r2 = 5, center = false)
Best regards,
Youbao
-----Original Messages-----
From:"Jordan Brown" openscad@jordan.maileater.net
Sent Time:2025-03-30 08:08:47 (Sunday)
To: zhangyoubao@siom.ac.cn, "OpenSCAD general discussion Mailing-list" discuss@lists.openscad.org
Cc: "Marius Kintel" marius@kintel.net
Subject: Re: [OpenSCAD] Re: How to output the AST nodes of an OpenSCAD scripting file?
On 3/29/2025 2:15 AM, zhangyoubao@siom.ac.cn wrote:
Thank you very much for your help. Now, we could get all the AST nodes information in the function of NodeVisitor::traverse(...).
Just to be clear, what you're looking at is a CSG dump, not an AST dump. It's a dump of the generated geometry, not a dump of the program that generates it. That makes it a lot easier to process, but of course it doesn't have the same flexibility.
You've probably looked at the definition of AbstractNode more recently than I have :-)
I don't see any level stored. I doubt that OpenSCAD would have any use for it in its own processing. For a CSG dump I think it just recursively walks the tree, and increments the indent whenever it descends.
You could certainly modify it to retain the original parameters (probably through creating subclasses of TransformNode, each of which had the right members), but it wouldn't be useful for OpenSCAD's core mission. Including those in a CSG dump would actually make CSG dumps harder to process, because the consumer would have to know about all of the possible transforms, not just about multmatrix.
What are you really trying to accomplish? I know you've talked about emitting Python, but for what purpose?