teepee changed the topic of #openscad to: OpenSCAD - The Programmers Solid 3D CAD Modeller | This channel is logged! | Website: http://www.openscad.org/ | FAQ: https://goo.gl/pcT7y3 | Request features / report bugs: https://goo.gl/lj0JRI | Tutorial: https://bit.ly/37P6z0B | Books: https://bit.ly/3xlLcQq | FOSDEM 2020: https://bit.ly/35xZGy6 | Logs: https://bit.ly/32MfbH5
<peepsalot> JordanBrown: why allow string based lookup if string can't be used in definition? unless { "a thing"= 123; } is valid?
<JordanBrown> See the current PR for a function that creates objects out of lists of name-value pairs.
<JordanBrown> o = object([["name1", "value1"], ["name2", "value2"]]);
<peepsalot> a function just to allow for feels wrong to me
<peepsalot> *for that
<JordanBrown> It does other things.
<JordanBrown> o = object(o1, o2)
<JordanBrown> merges the two
<JordanBrown> o = object(o1, name=value)
aiyion has joined #openscad
<JordanBrown> replaces a value. (Strictly, creates a new object with one value added or replaced.)
<peepsalot> btw, we do nearly have precedent for JSON-like syntax https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Customizer#Drop_down_box
<JordanBrown> Dimly similar, yes.
<peepsalot> i just feel that it is wrong to have no way to define literal object with a string key, unless a function is used
<peepsalot> how would the resulting objects look when echo'd ?
<JordanBrown> General, or ones that have non-identifier keys?
<peepsalot> non identifier keys
<JordanBrown> Not yet designed.
<JordanBrown> But probably, as in JavaScript, by putting them in quotes.
<peepsalot> that's why it should just go with JSON syntax in the first place
<JordanBrown> Except that these are not just name=value pairs, they are full OpenSCAD syntax.
<JordanBrown> x = { cube(10); } will give you a representation of a cube.
<JordanBrown> BTW, here's what it looks like now, in the development snapshot:
<JordanBrown> ECHO: { nominal = { ascent = 12.5733; descent = -2.9433; }; max = { ascent = 13.6109; descent = -4.2114; }; interline = 15.9709; font = { family = "Liberation Sans"; style = "Regular"; }; }
<peepsalot> i said it before but this is the first time we would break that echo'ing a value results in valid OpenSCAD syntax as well
<JordanBrown> Hmmmmm
<JordanBrown> I don't have an answer for that, other than that it seems unlikely that there are a lot of cases of taking random echo output and trying to feed it back into OpenSCAD.
<JordanBrown> Syntactically we could allow expressions to have identifiers on the left in quotes, but that doesn't give me warm fuzzy feelings. For one thing, in a non-object context, you couldn't access them.
<peepsalot> unless we go with javascript solution again, of providing a top level global object
<JordanBrown> True.
<JordanBrown> (Though I don't think JS has an object that is "all variables that you can access from the current context". I think it only has that for the global scope.)
<peepsalot> i don't know what the solution should be for geometry-type object members. but as discussed earlier, i think there should be some way to access individual geometries (probably using the GeometryList type internally).
<JordanBrown> The first big question is whether o = { cube(10); } returns a representation of a cube, or returns a polyhedron with 8 vertexes and 12 triangles.
<peepsalot> which makes me wonder if we should allow a Lua-like feature of "tables" which can have string keys, AND/OR numbered values like an array. so all geometries would become numbered
<JordanBrown> Well, we do have lists.
<JordanBrown> So we have a way to represent number-indexed collections of things.
<peepsalot> lists can't contain geometry
<peepsalot> or will they in the end plan?
<JordanBrown> Once we have a way to have geometry as data, they can.
califax has quit [Remote host closed the connection]
<peepsalot> so, should say "o.geometry" return a list of geometries?
califax has joined #openscad
<JordanBrown> Perhaps. That's one of the currently-unanswered questions: how you extract geometry from an object.
<JordanBrown> o.geometry is an obvious answer, but reserved names are yucky.
<JordanBrown> geometry(o) is another possibility, though having the geometry be in some sense a "hidden member" is also ugly.
<linext> i just imported 3000+ TTF fonts from Google's Web Font repo
<linext> my primitive customizer is back online: http://jbcse.com/customizer/
J1A848616 has joined #openscad
J1A8486 has quit [Ping timeout: 252 seconds]
pah has quit [Ping timeout: 244 seconds]
ur5us has quit [Ping timeout: 244 seconds]
pah has joined #openscad
<InPhase> peepsalot: I have been endorsing no access to geometry other than render(obj);
ccox has joined #openscad
<InPhase> peepsalot: Which could be plain "render(obj);" to simply display the geometry of that object at that location, or "data = render(obj);" to do the same as the current PR for this.
<InPhase> peepsalot: But where plain "render(obj);" should feel free to do the preview things if preview is on.
<InPhase> And if you really wanted to force it to render in a preview context, the syntax would be "render() render(obj);" Slightly wonky in that edge case, but the parallels between "render(obj);" and "data = render(obj);" are nice enough to make this a good choice.
<InPhase> peepsalot: I currently anticipate no value to reflection perusal of the CSG tree, but simply want to give flexibility for passing the pre-calculated geometries around, plus give access to the vertices and facets if desired.
<InPhase> But, leaving reflection perusal of the CSG tree unimplemented leaves the space open to add that functionality in later, if someone comes up with a sensible syntax at a later date.
pah has quit [Ping timeout: 252 seconds]
<InPhase> (And a sensible use case, which is currently missing.)
<InPhase> For the moment, I think providing access to that is more hazardous to development than helpful, because it means changes to the internal CSG tree representation for optimization purposes suddenly become breaking changes to the language API.
pah has joined #openscad
ur5us has joined #openscad
Nohus has quit [Ping timeout: 252 seconds]
<JordanBrown> I'm a little dubious of that particular concern, because I think those optimizations would probably be done as a prelude to rendering, rather than as a part of creating the CSG tree. However, since I don't have any sensible use cases...
<JordanBrown> Sadly, right now it looks easy to get the parsing to work right, not too hard to extract and return the geometry, and difficult to extract the variables. (If I'm reading this right, the module's local variables are rooted in a stack variable that only exists long enough to evaluate the module, and
<JordanBrown> is destroyed before you get back to the caller.)
pah has quit [Ping timeout: 252 seconds]
pah has joined #openscad
snakedLX has joined #openscad
<peepsalot> InPhase: I wasn't really thinking about CSG tree reflection, more like just iterating over multiple resulting geometries (assuming lazy-union enabled)
<peepsalot> i keep thinking we should probably have a children()/$children analogue for this (children works on AST nodes, not a list of geometries)
LordOfBikes has quit [Ping timeout: 244 seconds]
<peepsalot> InPhase: did you see the part of the discussion about convex decomposition? how can/should something like that be implemented?
<peepsalot> another example use case of returning two distinct geometries, would be what I call a "cleave" operation, splitting one geometry into two for a given plane
hervyqa has joined #openscad
hervyqa has quit [Client Quit]
hervyqa has joined #openscad
LordOfBikes has joined #openscad
hervyqa has quit [Quit: Konversation terminated!]
SamantazFox has quit [Remote host closed the connection]
SamantazFox has joined #openscad
snakedLX is now known as snaked
<InPhase> peepsalot: I suppose with this proposal in place it would be pretty natural to return a list of geometry-only objects.
<InPhase> That's much more flexible than any sort of children approach.
<peepsalot> InPhase: return from what? render? how do you take a geometry object and add to the scene? is "obj;" a valid statement?
<peepsalot> i feel like that should be valid
<InPhase> No, I mean the return from some new convex decomposition built-in could be done like that.
<InPhase> obj; would be like saying x = 5; x;
<InPhase> So for example, obj_list = convex_decomposition() FooModule(); for (i=[0:len(obj_list)-1]) { translate([10*i, 0, 0]) render(obj_list[i]); }
<InPhase> That's plenty clean enough to work with.
<InPhase> I think it also feels like a good fit with the general structure of the language.
qeed_ has joined #openscad
<peepsalot> InPhase: a statement from a variable with no geometry should be an error imo. i think its weird to call render, especially if you are saying that it would not actually force CGAL during preview
qeed has quit [Ping timeout: 244 seconds]
<peepsalot> its like wherever you get the geometry object from, the module has already been instantiated, so I feel like it is enough to use the variable itself as the statement
<peepsalot> i think overloading render like that would cause more confusion
<peepsalot> InPhase: do you have an idea in mind for how to get individual geometries out of: obj = { cube(10); sphere(5); }; ?
<peepsalot> would that also require a render? obj_list = render(obj); i'm actually confused
<InPhase> peepsalot: The idea is to specifically disallow it.
<InPhase> Or at least, to intentionally provide no support for it.
<InPhase> (And maybe someone could change their mind and add it later if there were a use case for it.)
<InPhase> But basically, object geometries should be a "unit".
<InPhase> Like, x = 5+3; How do you get back the 5 and the 3? You don't...
<InPhase> The value of x is 8. The value of obj is the union of the cube and the sphere.
<peepsalot> i would agree if not for wanting to actually fully support lazy union some day
<InPhase> That's the whole point of disallowing access.
<InPhase> It's not user-accessible. Internally, grab away.
<InPhase> Rearrange at will.
<InPhase> As far as the user is concerned, it should behave "as-if" it were a unified object.
<InPhase> And as I said, I'm not sure it needs to stay that way, but this is the easiest and most flexible approach in terms of not painting us into a corner, and it doesn't really disrupt any of the critical applications of this approach.
<InPhase> If you really want a separate cube an sphere, the syntax would not be { cube(10); sphere(5); }, but instead, [{cube(10);}, {sphere(5);}] Then, index away.
<peepsalot> hmm, i suppose...
<peepsalot> i still don't like the use of render for placing a geometry. that along with "data = render();" makes 3 different use cases
<InPhase> Also, one could object chunk it with: obj = { a = {cube(10);}; b = {sphere(5):}; render(a); render(b); }; Then, render(obj); contains both elements, or render(obj.a); is just the first one. So you still get the option to separate things out if you want it for a special case.
<InPhase> peepsalot: Well proposal 1 was to do geometry(obj); But that introduces a new keyword, and I think it actually feels more right to provide a different sort of input to render.
<InPhase> Would you rather: data = render() geometry(obj); Or, data = render(obj); ?
<peepsalot> btw for the data = render(); idea. data would be a polyhedron compatible list like this? [[<points...>], [<faces...>]]? or is data == { points=[<points...>]; faces=[<faces...>]; } ?
<peepsalot> or is data actually just a geometry object?
<InPhase> I think the latest proposal was that it was a geometry object with points, faces, and maybe a bbox.
<InPhase> But I'd have to go check where that PR ended up. I didn't track it as closely as I wanted to.
<InPhase> So many things going on at once. :)
<peepsalot> weit, so you can introspect a geometry object now? or we would have two diffrernt geometry value types
<InPhase> Sorry, I meant to type data object.
<InPhase> It's all just an "object", but an object can have data members and/or a geometry.
<InPhase> From data=render() you just get the data of points, faces, etc.
<peepsalot> ok, yeah data object seems reasonable. but back to render(obj), i thought the consensus was (after search) that excessive overloading was a Bad Thing
<InPhase> Well... I suppose it wouldn't hurt to throw the geometry in there too.
<InPhase> It's already being calculated after all.
<InPhase> data = render() Foo(); Then, render(data); :)
<peepsalot> bleh i was thinking polyhedron(**data);
<InPhase> I was thinking of adding a special parameter to polyhedron to take these data objects.
<InPhase> But if we toss the geometry along with, maybe that's superfluous.
<peepsalot> what would you think of a python style splat/unpack operator in general though?
<InPhase> I approve.
<InPhase> * to unpack list, ** to unpack object.
<InPhase> And likewise to receive a list or object as the parameters.
<InPhase> We'd get forwarding functions and modules.
<peepsalot> <InPhase> data = render() Foo(); Then, render(data); :) -- then there's the 3rd usage of just how we use render() currently
<InPhase> f(x=5, y=6); after function f(**params) = params.x + params.y;
<InPhase> peepsalot: Yeah, that doesn't bother me.
<InPhase> peepsalot: I think they are sort of in a family of behaviors.
<peepsalot> ok, but why does using a geometry object as a statement bother you though?
<InPhase> Well firstly because geometry is not a verb.
<peepsalot> neither is cube()
<InPhase> Yes, but I'm declaring a cube. :)
<InPhase> I feel like this is a transformative operation.
<peepsalot> tranforming what?
<InPhase> The object with a geometry literal information into a rendered instance of it at that location.
<peepsalot> you're literaly taking an already computed geometry and "placing" it into the output
<InPhase> I wouldn't cry tears over "geometry", just feels a little instinctively off as a word.
<InPhase> My primary interest is in the core features of this arrangement.
<InPhase> Swapping out the word would be small to me. BUT, I do think data = render(obj); should be valid, for sure.
<InPhase> If others prefer geometry(obj); then to place it, fine.
<peepsalot> data = render() obj;
<InPhase> That would need to be data = render() geometry(obj); or something like that.
<peepsalot> why?
<InPhase> Well, I guess it feels weird to just list objects and have them appear;
<InPhase> I guess at the very least that's very compact though.
<peepsalot> that's how the language works though the way I see it, lol
<InPhase> translate([10,0,0]) obj; translate([-10,0,0]) obj;
<InPhase> I suppose that could grow on me too.
<peepsalot> cube(); instantiating the module cube() creates a geometry, which then appears in ouput
<InPhase> The critical thing is don't let anyone talk you into obj();
<peepsalot> yes, agreed
<InPhase> I suppose that keeps render at just the current one usage plus the new PR as a completely uncoupled thing.
GNUmoon2 has quit [Remote host closed the connection]
<InPhase> And it will improve our OpenSCAD code golf scores.
<peepsalot> :D
<InPhase> JordanBrown: Read above, and see if you are also talked into data = render() obj; translate([10,0,0]) obj; translate([-10,0,0]) obj;
GNUmoon2 has joined #openscad
<InPhase> I've been swayed.
<InPhase> It's still the same basic logic, but compact and less chance for some of the confusions of render overloading.
* peepsalot cheers
qeed has joined #openscad
qeed_ has quit [Ping timeout: 260 seconds]
<JordanBrown> I dislike "x = foo() bar", for any foo and any bar. You're in expression context and foo() is a function; the way that you pass arguments to functions is through their arguments.
pah_ has joined #openscad
<JordanBrown> With respect to just uttering "obj;" to add an object to the model... shrug. My instinctive reaction is to want some foo(obj) so that it can look like a module invocation rather than requiring new syntax. Also, I would worry a little about errors and confusion about when you can just utter a bare
<JordanBrown> word like that. Can you just say "cube;" to get a
<JordanBrown> default cube? Not that they are really the same kind of thing - cube() is a module and obj is an object, but I wouldn't be surprised if people are confused.
pah has quit [Ping timeout: 260 seconds]
<JordanBrown> If you can say "obj;", can you instead say "expr;", where expr is an expression that evaluates to an object?
<JordanBrown> If you have a list of objects, can you say "foo[3];"?
J1A84861654 has joined #openscad
<JordanBrown> If you had a function that returned an object, you clearly couldn't say "foo();".
lastrodamo has joined #openscad
pah has joined #openscad
pah_ has quit [Ping timeout: 252 seconds]
J1A848616 has quit [Ping timeout: 252 seconds]
<JordanBrown> If we were designing a language from zero, I probably *would* make it that a statement could consist of an expression that evaluated to an object - and that's how what OpenSCAD calls modules would be implemented; there would be no distinction between a function and a module. But we aren't.
<JordanBrown> (I keep wondering whether Python has a way to hook any values resulting from a statement execution, because if it did then I could use that as a way to add geometry to a model, and it would address one of my biggest problems with using Python as a basis for a CAD language.)
<JordanBrown> (The REPL can do it, but I never found a way for a program to hook values in the same way.)
aisa has quit [Quit: WeeChat 3.4.1]
ali1234 has joined #openscad
ur5us has quit [Ping timeout: 244 seconds]
ali1234 has quit [Quit: Leaving]
ali1234 has joined #openscad
ur5us has joined #openscad
qeed_ has joined #openscad
qeed has quit [Ping timeout: 252 seconds]
ur5us has quit [Ping timeout: 260 seconds]
castaway has joined #openscad
J1A84861654 has quit [Ping timeout: 252 seconds]
ur5us has joined #openscad
J1A84 has joined #openscad
J1A84 has quit [Ping timeout: 252 seconds]
J1A84 has joined #openscad
teepee_ has joined #openscad
teepee_ has quit [Remote host closed the connection]
teepee has quit [Ping timeout: 258 seconds]
teepee has joined #openscad
J1A84 has quit [Ping timeout: 252 seconds]
J1A84 has joined #openscad
J1A84 has quit [Ping timeout: 252 seconds]
Nohus has joined #openscad
ur5us has quit [Ping timeout: 244 seconds]
J1A84 has joined #openscad
teepee has quit [Remote host closed the connection]
teepee has joined #openscad
Nohus has quit [Quit: Client closed]
califax has quit [Remote host closed the connection]
califax has joined #openscad
califax has quit [Remote host closed the connection]
califax has joined #openscad
qeed__ has joined #openscad
qeed_ has quit [Ping timeout: 268 seconds]
teepee has quit [Remote host closed the connection]
teepee has joined #openscad
teepee has quit [Remote host closed the connection]
teepee has joined #openscad
<J1A84> hmm backups only created when render ..  now my SCAD vanished when previewing
<J1A84> oh  backups also created when preview .. guess the crash prevented the save of a backup
<InPhase> I do preview on save, and then save externally to trigger the preview, so I've never once lost data on action of the program under this workflow.
<InPhase> The only penalty is you can never render without previewing at least once when doing it that way.
<InPhase> But I have very few designs where that's an issue.
<J1A84> you using an external editor or?
<InPhase> Yeah, vim.
<J1A84> so  this alt+arrow  feature doesn't work
<InPhase> Well not in vim. :) But it works for me when I open the built-in editor.
<J1A84> i mean it is broken anyway
<J1A84> isn't the backup function in scad then any use for you?
<InPhase> Why would I need to backup something I already saved?
<InPhase> Also vim will approximately never crash.
<J1A84> that is what i mean .. but the backup works automatically
snaked has quit [Ping timeout: 244 seconds]
<InPhase> I check the OpenSCAD backup folder once in a while, and see a few entries in there scattered over a multi-year timescale.
<InPhase> Looks like right now most of them are from 2021.
<J1A84> however  how is it possible that  code crashes SCAD and the backup is not triggered BEFORE code is parsed?
<InPhase> Looks like MainWindow's compile function checks to see if it needs to reload, then checks to see if the parse_file object includes changes, then if it concludes it should compile it saves the backup. Then it parses the document.
<InPhase> The backup is only triggered though if the editor contents were modified.
<InPhase> So there are a few things it does beforehand. Theoretically one could go wrong. But it should all be before parsing I think.
J1A84 has quit [Quit: Client closed]
J1A84 has joined #openscad
<InPhase> And... actionRenderPreview has some sketchy logic with a GuiLocker mutex.
<J1A84> i think i had some  if() echo()  that  caused the crash
<InPhase> I'm not sure that logic is actually right. The behavior and the comments mismatch on the handling of that GuiLocker mutex.
<InPhase> So that's at least one thing that could cause a freeze-type crash.
<InPhase> Is it a freeze-type or a close-type crash?
<J1A84> close-type  (after a short freeze)
<InPhase> https://bpa.st/223Q You see the nonsense? If GuiLocker is locked, it returns and does not process the rest of the function. Then it locks it. Then there's a comment that says if it is called while locked it needs to trigger another event calling the same function. But that will never run if it was called when locked.
<InPhase> Instead it will only call it when it was initially unlocked.
<J1A84> doesnt it call the GuiLocker only if it is not locked
<InPhase> The logic of it simply does not make sense to me. Something to look at later though. I have some work to finish for now.
<InPhase> Something is definitely mismatched though. It might be the comment, or it might be that single shot should not be there.
teepee_ has joined #openscad
teepee has quit [Ping timeout: 258 seconds]
teepee_ has quit [Remote host closed the connection]
teepee has joined #openscad
J1A84 has quit [Quit: Client closed]
J1A84 has joined #openscad
guerd871 has quit [Ping timeout: 268 seconds]
guerd87 has joined #openscad
<peepsalot> <JordanBrown> I dislike "x = foo() bar", for any foo and any bar. You're in expression context and foo() is a function; the way that you pass arguments to functions is through their arguments.
<JordanBrown> peepsalot yes?
<peepsalot> the example was specifically for render(), which is a special case. i wouldn't really consider it a function, since it has module children
<JordanBrown> Your argument is circular.
<peepsalot> its a module with a return value
<JordanBrown> "render() is a special case because it has children, and it's OK that it has children because it is a special case".
<peepsalot> render() is already an existing module
<peepsalot> in its current state
<JordanBrown> Module, yes. Function, no.
<JordanBrown> The idea is to have a general syntax that embeds what we might call "top-level" OpenSCAD language in an expression. My theory, at least, is that { cube(10); } yields a data object that represents a cube.
<peepsalot> data = render() cube(); is supposed to also be valid, no?
qeed__ has quit [Quit: qeed__]
<JordanBrown> That's the data = render() ... proposal, but I am suggesting a different proposal that I think is less offensive and also integrates with object creation.
<JordanBrown> If { cube(10); } is a data object, then it can be used like any other data object. It doesn't need special child syntax. o = { cube(10); }; g = render(o); can work fine.
qeed has joined #openscad
<JordanBrown> Or directly g = render({cube(10);});.
<peepsalot> hmm, i didn't think your proposal was intended as mutually exclusive with data = render()
<JordanBrown> I would use words like "replace" or "refine" rather than "mutually exclusive".
<JordanBrown> They are trying to achieve the same goal, but I think we need the { ... } syntax and that once we have it we don't need the child syntax.
<JordanBrown> Also I have warmer fuzier feelings about how it interacts with the rest of the syntax.
<JordanBrown> One of the results of a render will be, say, a bounding box, right?
<JordanBrown> could you say bb = render() cube(10).bbox; ?
<JordanBrown> You could clearly say render({cube(10);}).bbox.
<JordanBrown> with the "render() child()" proposal you could say (render() cube(10)).bbox, and it would be more or less clear, but should the extra parentheses be necessary?
<peepsalot> bb = {render() cube(10)}.bbox; maybe that's more a question of operator precedence and associativity
<JordanBrown> Did you mean to use parentheses rather than braces there?
<peepsalot> yes, I'm getting mixed up with all the proposals
<JordanBrown> If you're using my o = { cube(10); } syntax then yes, that would work, but the render() there is the render module, not the render function.
<InPhase> peepsalot: That would need to be (render() cube(10)).bbox
<InPhase> peepsalot: {render() cube(10)} is a syntax error, because it attempts to create an object but the thing inside is an unassigned value with no semicolon after it.
<InPhase> Oh wait. That's a thing that makes a cube, with CGAL, but has no semicolon, but then there's no bbox for that.
<InPhase> You could do: bb = (render() {render() cube(10)}).bbox
* InPhase throws his hands up in the air and shrugs.
<InPhase> Perhaps it's imperfect, but at least it's still well-defined. :)
<peepsalot> one of the reasons I think that counting a object as a statement, is that it follows as basic replacement if "x = { cube(10); }", then "x;" is the same as "{ cube(10); };" which is a valid statement (only slightly redundant semicolon in the replacement)
<peepsalot> s/counting a object/an object should count/
<InPhase> Fair.
<JordanBrown> When you say
<JordanBrown> <InPhase> You could do: bb = (render() {render() cube(10)}).bbox
<JordanBrown> what is the inner render() doing for you?
<InPhase> Well nothing useful, but it officially calls CGAL and makes that a full render action (not preview type), then the geometry produced by that is turned into a value object by the outer render() because it's in a value evaluation context being inside of parentheses, which then gets accessed for its bounding box.
<JordanBrown> Right, but the outer render calls CGAL too.
<InPhase> It does. But on something that's already in CGAL form so that part is basically a no-op.
<InPhase> You could get the same by just bb = (render() cube(10)).bbox;
<JordanBrown> Or, in the syntax I prefer, render({render() cube(10);}) would work, but the inner render doesn't do anything for you.
<JordanBrown> Right, which I would phrase as render({cube(10);}).bbox.
<JordanBrown> without needing to introduce "child" syntax into expressions.
<InPhase> I think it's worth pointing out that I hate bb = (render() {render() cube(10)}).bbox even though I typed it. I generally like the syntax structure of data = render(), but it sure looks wonky when the meaning changes by () vs {}
<JordanBrown> Actually, come to think of it, expressions already have a similar syntax supporting let(), echo(), and assert(), and there the following stuff is an expression, not "top-level" syntax.
<JordanBrown> (Do we have a name for what I'm calling "top-level" syntax, the syntax that you can type into an empty OpenSCAD editor?)
<InPhase> Not sure.
<JordanBrown> Maybe "statement context" versus "expression context"?
<peepsalot> JordanBrown: i don't think your proposal can replace "data = render()", if you are keeping the geometry as a black box as you say. the point of data = render(), is that there is some way for user to get direct access to vertex/face data
<JordanBrown> {cube(10);} would yield a black box. (Actually, half-black, because {a = 1; cube(10);} would have the a be accessible.)
<JordanBrown> render({cube(10);}) would be totally open, a function that consumes black-box CSG data and returns some representation based on triangles.
<InPhase> peepsalot: It's conceivable that rather than render(obj) like I was previously suggesting, we should scrap that in favor of free "obj;" geometry making like you suggested, and morph data = render() Foo(); into data = render(Foo());
<JordanBrown> Probably [ { color=xxx; points: [ ... ]; faces=[ ...]; } ]
<JordanBrown> data = render(Foo()); would need to be data = render({Foo();});. You need to get from expression context into statement context.
<InPhase> peepsalot: That turns the abomination bb = (render() {render() cube(10)}).bbox into bb = render(render() cube(10)).bbox; which looks much cleaner and less mysterious.
<JordanBrown> except that the inner render() doesn't do anything for you, so you might as well just say bb = render({cube(10);}).bbox.
<InPhase> Granted you would never want to nest these, but just as an expression example of confusion versus clarity in the two usages.
<InPhase> JordanBrown: Of course.
<JordanBrown> I like the braces; they make it clear to me that we're changing context.
<InPhase> JordanBrown: But putting them together artificially highlights more clearly what you would interpret at a glance in complicated expressions.
<JordanBrown> BTW, note the parallel to what GNU C calls statement expressions: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html .
teepee has quit [Ping timeout: 258 seconds]
<peepsalot> InPhase: your data = render(Foo()); example seems wrong. i think that should be data = render({ Foo(); });
<JordanBrown> yes
<JordanBrown> Got to get into statement context.
<InPhase> peepsalot: Well both should be fine.
<peepsalot> I actually like that now that I think about it, that makes data = render a pure function rather than a weird function/module hybrid
<JordanBrown> yes
<JordanBrown> data = render(Foo()); would be legal syntax, but Foo() there is a function, not a module.
teepee has joined #openscad
<InPhase> peepsalot: Oh, I see what you mean. Then it's strictly taking a value, and not a special syntax that can hold geometries.
<InPhase> That means data = render only ever receives one thing, of object type, and turns its geometry as into data.
<InPhase> s/as into/into/
<peepsalot> yep i find that very agreeable
<peepsalot> <JordanBrown> With respect to just uttering "obj;" to add an object to the model... shrug. My instinctive reaction is to want some foo(obj) so that it can look like a module invocation rather than requiring new syntax. Also, I would worry a little about errors and confusion about when you can just utter a bare
<peepsalot> My argument here is that the module invocation/instantiation (requiring parenthesis operator) has already been performed, when obj was assigned.
<peepsalot> The error would go from being a syntax error to say an evaluation error (only if the bare "var;" is not an object type)
<JordanBrown> I agree that obj = { cube(10); }; obj(); would be wrong.
<JordanBrown> obj is not executable in any sense.
<JordanBrown> and so should not have parentheses.
<JordanBrown> But foo(obj); for some appropriate word foo would be OK.
<JordanBrown> That's a module that consumes a data object and produces geometry.
<JordanBrown> The problem in my mind is picking the word foo.
<peepsalot> i picture it more like the data object already contains geometry. so you don't need a special operation to produce and place the geometry into the model, just put the object which represents the geometry there
teepee has quit [Remote host closed the connection]
<JordanBrown> I understand that logic, and if we were designing a language from zero I might consider it.
<JordanBrown> But it's not "an object", exactly. It's a variable (ignoring semantic quibbling about whether OpenSCAD has variables) where the content is geometry.
teepee has joined #openscad
<JordanBrown> First, what would it mean to say "x = 5; x;"? Is it data-type-sensitive whether you can use a variable in that way? (Again, if we were starting from zero I would consider inferring a "print" operation there.)
<JordanBrown> Second, generally anywhere you can use a variable you can use an expression.
<peepsalot> if x is not object type, that is an error
<JordanBrown> So could you say list_of_o = [ { cube(10); }, {sphere(10);} ];
<JordanBrown> and then say list_of_o[1]; to put a sphere into the model?
<peepsalot> yes
<JordanBrown> Or obj_containing_o = { c = { cube(10); }; s = { sphere(10); } };
<JordanBrown> and then say "obj_containing_o.c;" to add the cube?
<JordanBrown> What about
<peepsalot> sure
<JordanBrown> function f() = { cube(10); };
<JordanBrown> could you say f(); to put that cube into the model?
<peepsalot> yes, with caveat that if a module f exists, then probably module takes precedence, and/or print a warning about ambiguous invocation
<peepsalot> basically any expression could become a statement. but i would consider it an error if that expression does not result in an object.
<JordanBrown> Introducing the namespace ambiguity is unpleasant.
<JordanBrown> And I would worry that the two syntaxes might collide.
<JordanBrown> That is, we're creating a case where we don't know whether we are in expression context or in statement context. Can you always disambiguate? Clearly not by syntax alone, as the f() example shows. But are there other cases that are syntactically ambiguous, that would get you into deeper trouble?
<JordanBrown> Just because two cases are theoretically syntacti
<JordanBrown> cally unambiguous doesn't mean that the parser can distinguish them.
<peepsalot> yeah the namespace issues are unfortunate. the parser will warn you during build if the rules are conflicting though.
<peepsalot> so I expect the module instantations vs bare expression (function call) would conflict, but i think it could be worked around. not sure if any other kind of conflicts would arise though
<teepee> at this point there should not be a collision because the left side of an assignment is only an identifier
<teepee> like there's no "." support on the left side
<peepsalot> teepee: not sure if we're talking about the same thing. I was trying to argue towards basically having another "| expr" line inserted here: https://github.com/openscad/openscad/blob/master/src/core/parser.y#L213
<peepsalot> with the idea that an object is valid statement on its own.
J1A84 has quit [Quit: Client closed]
J1A84 has joined #openscad
<teepee> I'm not sure that works, I suspect that will throw lots of conflicts
<JordanBrown> My concern exactly.
<JordanBrown> Allowing a bare "bar;" would be syntactically OK, but bothersome because I think it would be the only r-value case where you're only allowed to use a variable.
epony has quit [Quit: QUIT]
<teepee> that is what Doug proposed IIRC, I don't like the optics though ;-)
epony has joined #openscad
<JordanBrown> [ Got to do real work and lunch now. ]
p3ck has joined #openscad
ur5us has joined #openscad
LordOfBikes has quit [Read error: Connection reset by peer]
LordOfBikes has joined #openscad
teepee has quit [Remote host closed the connection]
teepee has joined #openscad
castaway has quit [Ping timeout: 252 seconds]
teepee_ has joined #openscad
teepee has quit [Ping timeout: 258 seconds]
teepee_ is now known as teepee
zauberfisch has quit [Ping timeout: 252 seconds]
zauberfisch has joined #openscad
teepee has quit [Remote host closed the connection]
teepee has joined #openscad
pah is now known as pa
lastrodamo has quit [Quit: Leaving]
califax has quit [Ping timeout: 258 seconds]
GNUmoon2 has quit [Ping timeout: 258 seconds]
califax has joined #openscad
califax has quit [Write error: Connection reset by peer]
teepee has quit [Remote host closed the connection]
califax has joined #openscad
teepee has joined #openscad
GNUmoon2 has joined #openscad
ccox has quit [Remote host closed the connection]
ccox has joined #openscad
ccox has quit [Ping timeout: 252 seconds]
qeed_ has joined #openscad
qeed has quit [Ping timeout: 268 seconds]
linext has quit [Ping timeout: 255 seconds]
GNUmoon2 has quit [Remote host closed the connection]