halcompile: reject declarations that claim the same HAL name - #4298
Conversation
ea6413a to
e1db816
Compare
|
Name collisions are bad by default and fail to compile. Why is there an option for this? You should be able to check this much easier using a parallel name array for target names (which you apparently do) without complex regexes or lambdas by using a simple Your second PR seems to be a duplicate and changes a generated (man) file that is not part of the repository. Why is this submitted twice? |
It's a 2.9 backport, no .adoc there, also threw me off... |
|
thanks. help me understand here. is this is a problem that can throw some people (amateurs using AI) off? if so and a little fix can help, I'll try to sharpen the solution. but if its not even an issue, i'll close the PR. |
e1db816 to
1188057
Compare
But they actually don't, I tested the claimed Edit: |
|
Still, the option is useless. |
ok I think this resolved the bit of confusion I as well as @grandixximo had. so this is a little problem that should be patched. but the option of hiding it is useless. i'll resubmit removing the option to hide it. thanks @BsAtHome |
1188057 to
6b100fc
Compare
|
Wasn't this initially showing also info that the pins you will find in hal have different names? |
Per component: that's already what it did — one line per file with the names collapsed into it (my_input -> my-input, ...). But the build runs halcompile once per .comp, so its still 100+ lines on a full master build. One line for the whole build: It would have to be a fixed message from src/hal/components/Submakefile, which then can't name any actual pins. Also, in-tree only, so out-of-tree authors never see it. I have no clue how folks use this so I'll leave it to you guys to tell me what to do. |
You did do that originally, but that part has been removed, that is what I was saying, it is not there anymore, check the code... |
|
Isn't this already described in https://linuxcnc.org/docs/devel/html/en/hal/comp.html ? |
|
Correct, but the OP, before edits (the whole reason this PR started), was because the user and his AI missed that, the original proposal was a noisy An addition in the --help will improve visibility, and will weaken the "is not well documented" argument, after the addition in --help there are less excuses for missing it, AI or human... |
|
The --help is there to remind you of command line switches. Not to tell you how to write content. That belongs to the man pages and other documentation. The man-page is terse and should link properly to the docs. And, as you correctly said, no new is good news and errors/warnings are supposed to be one-liner messages with the correct information (in the correct format for IDEs to use). Relying on abnormal intelligence to do the right thing is like asking an amoeba to write Shakespeare. The letters are there but the meaning is lost. As they say, gigo. |
|
The man page argument has a hole for exactly the audience halcompile serves: component developers. They overwhelmingly work from a RIP build (git clone, make, rip-environment), and RIP installs nothing to MANPATH. For them
There is also in-tree precedent for non-switch guidance in this very usage() text: "Do not use [sudo] for RIP installation" is behavioral advice, not a switch reminder. Not proposing a tutorial, just 4 lines stating the one non-obvious semantic (C identifier => dashed HAL name) plus where to see the result ( |
|
What is the status of progress? There are still some unaddressed open comments. |
|
@tzuohann is on vacation till mid September, just texted him on Discord... |
|
hi guys, back. i'll double check these before end of weekend. |
6b100fc to
edf5da2
Compare
All four addressed, and the branch is rebased onto master — it was 645 commits behind. Widening the tests as you asked turned up that the check itself was wrong in both directions, so it is rewritten: it now compares the set of HAL names a declaration claims, not its Force-pushed. All 146 in-tree .comp files preprocess to the same C, with the same exit status, as master. |
| # A pin array claims one HAL name per element. The bound keeps a nonsense | ||
| # size from expanding into a MemoryError instead of a diagnostic; an array | ||
| # larger than this cannot be loaded anyway, since every element is a separate | ||
| # HAL object in shared memory. | ||
| ARRAY_CLAIM_LIMIT = 4096 |
There was a problem hiding this comment.
Where does this limit come from? The default personality limit is 64 and max 256 IIRC (a byte size). Therefore, personality limited arrays never are larger than 64.
For normal arrays, if someone creates an array of 4097 pins, should that fail? The current HAL memory allocation can support many more pins than 4096.
From a practical standpoint, having really many pins in an array would probably indicate some kind of error or abuse. I'd probably say it is an error and we may want to limit it to the same as the personality limit of 256. Unless there is a really good reason not to... You have one?
There was a problem hiding this comment.
Mine (Claude's really), and its rather arbitrary — only to stop a MemoryError while expanding element names. 256 now, as you suggest; the largest array in the tree is 32 elements, so nothing in-tree changes.
Commet/correction: 256 isn't an existing limit. MAX_PERSONALITIES is 64, -P is uncapped, and a [MAXSIZE : CONDSIZE] array is bounded by MAXSIZE, not by MAX_PERSONALITIES.
There was a problem hiding this comment.
Mine (Claude's really), and its rather arbitrary
You outsourced your thinking. That equates to "I'm not learning".
Take it from a teacher: Learning comes at a price. That price is failing all the time until you don't fail anymore (or, at least, fail less). Outsourcing your learning process in this manner only learns you to write prompts. But, the output it generates you cannot fathom or comprehend. Learning the output's meaning means you have to create it yourself, fail, try again, fail, etc, until that you write works and understand how and why. That process generates insight in all directions, which no automated process can provide. Learning is hard and only those who learned hard have learned.
— only to stop a MemoryError while expanding element names. 256 now, as you suggest; the largest array in the tree is 32 elements, so nothing in-tree changes.
When do you suppose the memory error will pop up? How many elements can you generate before your machine generates an error? Instead of capping at the expansion of the names, it may be better to cap at the
Commet/correction: 256 isn't an existing limit. MAX_PERSONALITIES is 64, -P is uncapped, and a [MAXSIZE : CONDSIZE] array is bounded by MAXSIZE, not by MAX_PERSONALITIES.
Normal arrays are bounded by their definition in the source (runtime). Pins with a personality attribute are capped by that attribute at runtime. The max array size at halcompile-time is indeed unbounded and potentially problematic.
The 256 comes from logic.comp where the personality is and'ed with 0xff, which makes any larger value impossible. This seems to be a reasonable bound for others as well.
Therefore, the change to 256 is probably the best for now.
There was a problem hiding this comment.
I'm not going to push back on the very accurate educator's perspective - I was a professor for 8 years. This is lazy learning and less than ideal but I am 42. I just don't have the time. My main priorities at the moment are being a father, and getting a business in a field completely orthogonal to my work experience off the ground. Will try to contribute where I can and I decided I wanted to do so transparently, citing Claude as a tool, and taking the blame if its done poorly. It's the standard "all errors are mine" disclaimer.
Also, if AI comes for us with robodogs, I'll be classified as "AI ally human" side. :-), That is, until it sees this comment and understands sarcasm.
Do continue to comment in detail. It is appreciated and it helps me understand it. I do take your comments as input and ask Claude to explain them to me - subject to my bandwidth constraint. At some point, when I have a breather, I will come back and try to understand things properly. That will happen if I get the luxury of sitting and developing tech while someone else runs a business (looking at Luca).
There was a problem hiding this comment.
Also, logic.comp's & 0xff is a better justification than I had. Thanks.
|
And, your work is much appreciated. Detecting duplicates is a hard problem and solving it is quite involved. That is why I'm looking deep. |
This stuff is honestly way the hell over my head and every comment is some coding class I should have taken years ago. |
edf5da2 to
4ac6bfd
Compare
| def Error(msg, *args, pos=None): | ||
| if args: | ||
| msg = msg % args | ||
| raise runtime.SyntaxError(S.get_pos(), msg, None) | ||
| raise runtime.SyntaxError(pos or S.get_pos(), msg, None) | ||
|
|
There was a problem hiding this comment.
Why do you need to change the behaviour of the Error() function?
You are adding a named parameter, but where in the code is that used?
Am I missing something?
There was a problem hiding this comment.
claim() passes it through; nothing else.
pos facilitates avoiding a confusing error message. Consider a userspace component with function _ left in and a pin called time. Userspace components get no functions, so .time is never created. If the check runs at the declaration it errors about something that doesn't exist - confusing especially if one traces backwards.
That is why the check waits until the end of the file, so pos remembers where the function was.
It is one optional argument and defaults to the old behavior. Your call.
A name declared in a .comp file is exported under a mangled HAL
identifier: underscores become dashes and a trailing dash or period is
removed (comp.adoc, HALNAME). check_name_ok() compares only declared
names, so a component declaring both x_y and x_y_ exported both as x-y.
halcompile accepted it and the module failed at loadrt:
HAL: ERROR: duplicate pin 'collide.0.x-y'
collide: rtapi_app_main: Invalid argument (-22)
A declaration does not claim one name, so comparing mangled declared
names is not enough:
- an array claims one name per element, and to_hal() turns the "#"
block into a printf conversion, so 'x_#[4]' and 'x_0' both claim
x-0 while their mangled forms never compare equal;
- hal_export_funct() creates <funct>.time, .tmax and .tmax-increased
in the pin and param namespace, so 'function f' and 'pin f.time'
collide although only one of them is written down. Those are
claimed in the last rule of the grammar rather than at the
declaration, since a userspace component exports no function and
'option userspace' may follow it.
claim() therefore records the set of HAL names each declaration takes.
Pins and params share one set, because hal_lib.c refuses a pin whose
name is already a param and the reverse; functions have their own. An
'if' condition does not exempt a declaration: telling two conditions
apart would mean evaluating the C, and overlapping personality pins are
a design error anyway.
Arrays are limited to 256 elements. The largest in the tree is 32.
Two shapes master accepts are now refused: an array over 256 elements,
and two declarations that claim one name under mutually exclusive 'if'
conditions.
Docs: NAMES section in the halcompile man page, linking to the HALNAME
rules in comp.adoc, which gains a [[sec:halname]] anchor to link at.
Tests: tests/halcompile/halname covers pin/pin, pin/param,
function/function, array/scalar, function/derived-pin and personality
collisions and the array limit, and asserts that a pin and a function
mangling to one name are accepted, since their namespaces differ.
All 146 .comp files on master preprocess to the same C, and with
identical exit status, as master.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4ac6bfd to
dbd1c03
Compare
|
dammit bertho, merge my PR. i pour myself a whiskey every time one gets accepted, and its my damn birthday. its just a huge thrill to get one in. getting it right matters more obviously. |
pin in real my_inputis exported ascomponent.N.my-input— underscores become dashes (comp.adoc, HALNAME).A component that declares both
x_yandx_y_exports both asx-y. halcompile accepts it; the module then fails at loadrt:check_name_ok()only compares declared names. Comparing mangled names is not enough either, because a declaration does not claim just one:x_#[4]andx_0both claimx-0;hal_export_funct()creates<funct>.time,.tmaxand.tmax-increasedin the pin/param namespace, sofunction fandpin f.timecollide.claim()records the set of names each declaration takes and rejects a repeat at the offending line. Pins and params share one set; functions have their own. Anifcondition does not exempt a declaration.Arrays are limited to 256 elements.
Two shapes master accepts are now refused: an array over 256 elements, and two declarations claiming one name under mutually exclusive
ifconditions.Docs: NAMES section in the halcompile man page, linking to a new
[[sec:halname]]anchor in comp.adoc. Tests:tests/halcompile/halname. All 146 in-tree.compfiles preprocess to the same C, with the same exit status, as master.🤖 Generated with Claude Code