Just a few things I have noticed.
I ran it against an OpenSCAD file designed to be run through the customizer,
and saw a few things.
parsing publicDomainGearV1.1.scad
publicDomainGearV1.1.scad:63:2: W2002: Overwriting mm_per_tooth
variable
from a lower scope.
publicDomainGearV1.1.scad:65:2: W2002: Overwriting thickness
variable from
a lower scope.
publicDomainGearV1.1.scad:74:47: W2008: Variable pi
used but never
defined.
publicDomainGearV1.1.scad:75:14: W2008: Variable p
used but never defined.
...
publicDomainGearV1.1.scad:79:9: W1001: Overly complicated argument contains
9 tokens.
I wrote a small test program to check a few of these, and got:
parsing Test.scad
Test.scad:2:15: W2002: Overwriting x
variable from a lower scope.
Test1 illustrates the first problem. In a module, a parameter can have a
default value.
Test2 does not duplicate the errors shown for lines 74 and 75 of
publicDomainGearV1.1.scad
About the line 79:9 "Overly complicated argument", I'm not sure that's a
problem. I admit I am not an expert OpenSCAD user, but it seems to me that a
valid startement using any number of arguments should not generate a warning
or error.
publicDomainGearV1.scad
http://forum.openscad.org/file/t2121/publicDomainGearV1.scad
Test.scad http://forum.openscad.org/file/t2121/Test.scad
Nice work.
--
Sent from: http://forum.openscad.org/
Yeah exactly what rules we put in are an interesting question and there will
always be differences of opinion, and the best way to deal with this is to
make them customisable.
For context of the microscope we are looking to move the microscope design
towards something that could be medically certified. For this we need a lot
of confidence that every piece of code behaves as expected.
Overwriting a variable from a lower scope can cause a piece of code to
change behaviour unexpectedly or to confuse someone on which variable is
being used. It is then safer to pass in arguments than overwrite a variable.
We are also likely to warn that include in itself is dangerous. So in the
example of Test.scad
if you remove line 1 then it doesn't warn. So it is
fine to override the the default input, but it warns if a variable in that
scope has the same name as one defined in the lower scope. These warnings
are annoying to a lot of people. So we may perhaps turn them off by default
and have a mode that is more like
sca2d --strict file.scad
The same logic goes for overly complicated argument. It is again for
readability and understandability of out code. The idea is to try get
someone to change:
cube([17*2+0.1*25.4*2+35, 17*2+0.1*25.4*2+75, 17*2+0.1*25.4*2+45]);
To:
wall_thickness = 17;
inch = 25.4;
//clearance is 1/10 of an inch as recommended by the manufacturer on p19
clearance = 0.1*inch;
inner_dimensions = [35, 75, 45];
extra_size = (wall_thickness+clearance)*2*[1,1,1];
cube(inner_dimensions + extra_size);
Both should be identical. But one is more understandable. Of course, the
analyser can only go so far. There are always ways just define a pointless
badly named variable just to reduce the number of tokens. But the analyser
is to help you identify confusing code. Most statements the analyser picks
up will be valid code, they just are things that may confuse someone else
reading it.
The key to this has to be configurability so a project can decide what the
want to allow. It would be interesting to get feedback from the community
about what dangerous/confusing code they would want to be warned about.
--
Sent from: http://forum.openscad.org/
julianstirling wrote
Yeah exactly what rules we put in are an interesting question and there
will
always be differences of opinion, and the best way to deal with this is to
make them customisable.
For context of the microscope we are looking to move the microscope design
towards something that could be medically certified. For this we need a
lot
of confidence that every piece of code behaves as expected.
Overwriting a variable from a lower scope can cause a piece of code to
change behaviour unexpectedly or to confuse someone on which variable is
being used.
I haven't tried the analyzer, but I think that in a case like this:
function myfunc(parm1, parm2) =
let(
parm2 = is_undef(parm2) ? parm1 : parm2,
....
)
it is more clear to define parm2 in the lower scope as I do above than it
would be to do something like
function myfunction(parm1, parm2_temp)
let(
parm2 = is_undef(parm2_temp) ? parm1: parm2_temp,
....
)
It is then safer to pass in arguments than overwrite a variable.
Technically speaking it's impossible to overwrite a "variable" in OpenSCAD.
You can only define new ones.
--
Sent from: http://forum.openscad.org/
Has anyone tried OpenSCAD on any of the new Apple Silicon machines (MacBook
Air/Pro or Mac Mini with the M1 processor)?
The latest nightly doesn't appear to be compiled as Universal 2. Although
Rosetta 2 seems to be handling most things really well by all reports, I
can easily see the kind of stuff that OpenCSG is doing potentially having
bugs on the new GPUs.
I'm looking to upgrade soon, but I really need to be able to run OpenSCAD,
and its support for the new machines is currently my biggest question mark.
On 21.11.20 01:14, Whosawhatsis wrote:
Has anyone tried OpenSCAD on any of the new Apple Silicon machines
(MacBook Air/Pro or Mac Mini with the M1 processor)?
Yep, that would be interesting to hear.
The latest nightly doesn't appear to be compiled as Universal 2.
Although Rosetta 2 seems to be handling most things really well
by all reports, I can easily see the kind of stuff that OpenCSG
is doing potentially having bugs on the new GPUs.
I don't know if it will be possible to do anytime soon. Right
now it's not clear how to support MacOS if more of the services
currently free for open source projects are closing down and/or
are limiting availability.
ciao,
Torsten.
Looks like Github Actions has a MacOS 11 build environment.
https://github.com/actions/virtual-environments/issues/1814
It is free for public repositories.
On Fri, Nov 20, 2020, at 7:42 PM, Torsten Paul wrote:
On 21.11.20 01:14, Whosawhatsis wrote:
Has anyone tried OpenSCAD on any of the new Apple Silicon machines
(MacBook Air/Pro or Mac Mini with the M1 processor)?
Yep, that would be interesting to hear.
The latest nightly doesn't appear to be compiled as Universal 2.
Although Rosetta 2 seems to be handling most things really well
by all reports, I can easily see the kind of stuff that OpenCSG
is doing potentially having bugs on the new GPUs.
I don't know if it will be possible to do anytime soon. Right
now it's not clear how to support MacOS if more of the services
currently free for open source projects are closing down and/or
are limiting availability.
ciao,
Torsten.
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
julianstirling wrote
Yeah exactly what rules we put in are an interesting question and there
will
always be differences of opinion, and the best way to deal with this is to
make them customisable.
Agreed.
Overwriting a variable from a lower scope can cause a piece of code to
change behaviour unexpectedly or to confuse someone on which variable is
being used. It is then safer to pass in arguments than overwrite a
variable.
We are also likely to warn that include in itself is dangerous. So in the
example of Test.scad
if you remove line 1 then it doesn't warn. So it is
fine to override the the default input, but it warns if a variable in that
scope has the same name as one defined in the lower scope. These warnings
are annoying to a lot of people. So we may perhaps turn them off by
default
and have a mode that is more like
sca2d --strict file.scad
Sounds good. I see a LOT of people using defaults for variables, and using
the same names. I can understand the reasoning on both sides. Some want to
name it the same as the external one so it is clear what its purpose is, and
to supply a default value. Others (possibly those that see variables in
openSCAD as being actual variables), as being redefined. Both sides might
see the opposite as confusing.
You did not mention it, but what about the "variable used but never
defined"?
publicDomainGearV1.1.scad:74:47: W2008: Variable pi
used but never
defined.
publicDomainGearV1.1.scad:75:14: W2008: Variable p
used but never defined.
I see that when I remove the assign() (which is deprecated), it no longer
gets flagged, so that may be the reason for it.
The same logic goes for overly complicated argument. It is again for
readability and understandability of out code. The idea is to try get
someone to change:
cube([17*2+0.1*25.4*2+35, 17*2+0.1*25.4*2+75, 17*2+0.1*25.4*2+45]);
To:
wall_thickness = 17;
inch = 25.4;
//clearance is 1/10 of an inch as recommended by the manufacturer on
p19
clearance = 0.1*inch;
inner_dimensions = [35, 75, 45];
extra_size = (wall_thickness+clearance)2[1,1,1];
cube(inner_dimensions + extra_size);
Fair enough, but there are things that simply can't be reduced, so where
would you set the limit?
In the file I referenced, line 123:7 is a good case in point. All those
variables are used in the module.
Both should be identical. But one is more understandable. Of course, the
analyser can only go so far. There are always ways just define a pointless
badly named variable just to reduce the number of tokens. But the analyser
is to help you identify confusing code. Most statements the analyser picks
up will be valid code, they just are things that may confuse someone else
reading it.
The key to this has to be configurability so a project can decide what the
want to allow. It would be interesting to get feedback from the community
about what dangerous/confusing code they would want to be warned about.
Well, this has been feedback for you, and I am happy that you see the
desirability of allowing preferences to be set.
I do like the "Function defined but never used" and the "Semicolon not
required" reporting.
Again, nice work.
--
Sent from: http://forum.openscad.org/
@lar3ry
"You did not mention it, but what about the "variable used but never
defined"? "
So used but never defined, should catch an error, that will happen in some
paths of the code. I can well believe there is a bug in how I count it at
the moment. The program is less than a week old :)
The "X defined but never used" warnings need a bit of nuance. A library of
modules/functions that are for others to "use", or a library of variables
for others to "include". They are defined but not used for a very good
reason! At the moment SCA2D just shouts about all of them. I think that
defining something in a module/control scope and never using should generate
a warning. In the outer-scope, it probably should not for libraries.
I say "it should not for libraries" but obviously any file can be used as a
library. I think this is where again we may for our specific purposes have a
strict mode where we somehow divide files into libraries that define modules
and functions but don't use them. And geometry files that use everything
they declare. This is a useful separation for our purposes but not a sane
default I would want to "impose" on others.
"Fair enough, but there are things that simply can't be reduced, so where
would you set the limit?" This I think is the key question. One thing I am
starting to do now is recategorise the warnings more sensibly. Using
something before it is defined is an Error and should have an E code, not
using something within a module scope is a Warning and should have a W code.
Complexity should be listed under "consider refactoring" with an R code.
I think the important thing about code analysis is that there is always the
option to ignore the message. So when I program PyLint tells me off when a
class has too many attributes, or when a method is too complex. Sometime I
will look at the Class/Method and go "Eh, you know, it is fine as it is.".
Other times I will look at it and go "Wow that is getting out of hand, I
should tidy it up.". The code analysis is a great way to locate potentially
confusing things and then deciding if you want to fix them. However, if you
think it is fine, then the right thing to do is ignore the analysis. In
PyLint I used to put in little codes to disable a specific warning in a
specific place. I have stopped doing this now because as the code mature
these things grow until I really should look at them again.
Looking now at your specific example it is a long array... And a very clear
long array. I think I do really need a better way to calculate the
complexity of arrays because clearly the expression you flagged is a very
very clearly laid out expression. I have made a note of this and will fix
it. It won't be a quick fix because my complexity calculation is very overly
simplistic right now. Thanks for flagging this!
@adrianv
That example with the "let" is very interesting. I had not appreciated that
let could be used in that way. In fact, none of our code uses let in any way
so I just bashed it into the lexer/parser without much further thought.
Reading in more detail I do actually need to give it significantly more
thought as it is a very powerful new feature. Thanks for bringing my
attention to this :)
--
Sent from: http://forum.openscad.org/
I'm not sure how useful complexity warnings are in OpenScad. The nature of
the language requires some very complex syntax to accomplish almost any
non-trivial task...
On Sat, 21 Nov 2020, 07:37 julianstirling, julian@julianstirling.co.uk
wrote:
@lar3ry
"You did not mention it, but what about the "variable used but never
defined"? "
So used but never defined, should catch an error, that will happen in some
paths of the code. I can well believe there is a bug in how I count it at
the moment. The program is less than a week old :)
The "X defined but never used" warnings need a bit of nuance. A library of
modules/functions that are for others to "use", or a library of variables
for others to "include". They are defined but not used for a very good
reason! At the moment SCA2D just shouts about all of them. I think that
defining something in a module/control scope and never using should
generate
a warning. In the outer-scope, it probably should not for libraries.
I say "it should not for libraries" but obviously any file can be used as a
library. I think this is where again we may for our specific purposes have
a
strict mode where we somehow divide files into libraries that define
modules
and functions but don't use them. And geometry files that use everything
they declare. This is a useful separation for our purposes but not a sane
default I would want to "impose" on others.
"Fair enough, but there are things that simply can't be reduced, so where
would you set the limit?" This I think is the key question. One thing I am
starting to do now is recategorise the warnings more sensibly. Using
something before it is defined is an Error and should have an E code, not
using something within a module scope is a Warning and should have a W
code.
Complexity should be listed under "consider refactoring" with an R code.
I think the important thing about code analysis is that there is always the
option to ignore the message. So when I program PyLint tells me off when a
class has too many attributes, or when a method is too complex. Sometime I
will look at the Class/Method and go "Eh, you know, it is fine as it is.".
Other times I will look at it and go "Wow that is getting out of hand, I
should tidy it up.". The code analysis is a great way to locate potentially
confusing things and then deciding if you want to fix them. However, if you
think it is fine, then the right thing to do is ignore the analysis. In
PyLint I used to put in little codes to disable a specific warning in a
specific place. I have stopped doing this now because as the code mature
these things grow until I really should look at them again.
Looking now at your specific example it is a long array... And a very clear
long array. I think I do really need a better way to calculate the
complexity of arrays because clearly the expression you flagged is a very
very clearly laid out expression. I have made a note of this and will fix
it. It won't be a quick fix because my complexity calculation is very
overly
simplistic right now. Thanks for flagging this!
@adrianv
That example with the "let" is very interesting. I had not appreciated that
let could be used in that way. In fact, none of our code uses let in any
way
so I just bashed it into the lexer/parser without much further thought.
Reading in more detail I do actually need to give it significantly more
thought as it is a very powerful new feature. Thanks for bringing my
attention to this :)
--
Sent from: http://forum.openscad.org/
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
I have pushed out v0.0.4. You can get the newest version by running:
pip install sca2d --upgrade
Thanks to the the helpful feedback of @lar3ry I have realised I was handling
assign statements incorrectly. This is fixed so they throw a sensible
depreciation message not a variable used before definition error.
Also thanks to @adrianv, I have now implemented let expressions in the form
he mentioned. It does still throw the variable overwritten from lower scope
warning. I need to think about this some more.
I have also recategorised the warnings into Errors, Warnings, Depreciation
warnings, and Information. These have E, W, D and I codes. If you run:
sca2 --colour file.scad
it will colourise the errors (not checked this on Windows!). The Fatal
warnings when files cannot be read still sit outside my normal messaging
system so they are still just standard in colour.
I still haven't managed to get to some of the other errors that @nophead
found. But I have added the problems to the README.
Finally to @acwest. I think that the nature of OpenSCAD is that it is a
low-level language. While you need to do quite a number of commands to
accomplish tasks, there is nothing stopping you breaking these up into
variable, smaller functions and modules. The concepts of cognitive
complexity and cyclotomic complexity have been for programming date back to
the 1980s or before, back when almost all languages were low level and
required a large number of commands to perform a simple task. The idea is to
break things down into managable chunks that can be digested.
--
Sent from: http://forum.openscad.org/