|
|
Harrumph - lucky you is all I can say.
Back in the late eighties I was working in Bahrein, and had to make a trip over the causeway to Al Khobar, where I happened upon a HiFi shop that sold me a set of Stax electrostatic 'Ear speakers' - much too posh to be just headphones. They cost around five hundred bucks, which I thought pretty good back then.
Move on thirty plus years, and I decided that as the power supply was dodgy, and the volume control a bit hit and miss, I would replace them. Off to Amazon I go, and then went into serious cardiac arrhythmia. Three and half thousand ing quid!
Needless to say, the soldering iron was wheeled out and a massive amount of TLC applied. The volume control is now external, as the original was part of the circuit board, and the power supply replaced and directly soldered to the board as the socket had cracked away from it.
MrsLadyWife is not overly enamoured with the four piece combo (headphones, power supply, amplifier and volume control) and a four metre cable littering 'her' drawing room, but the complaints lessen considerably when I mutter about spending £3.5k on a replacement.
The problem really stems from her liking to watch television of an evening, whereas I much prefer to read and listen to the great groups of yesteryear, like Mo's Art, Jo's off hidin' and Beat Oven.
|
|
|
|
|
OriginalGriff wrote: Repair, reuse, recycle ... you know it's worth it. Most companies are spending resources on preventing that
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
|
It is appreciated
Director of Transmogrification Services
Shinobi of Query Language
Master of Yoda Conditional
|
|
|
|
|
I have never been lonely except when I've been surrounded by people
"We can't stop here - this is bat country" - Hunter S Thompson - RIP
|
|
|
|
|
Isn't that the worst kind of loneliness?
|
|
|
|
|
So many lonely people, in an overpopulated world.
Your own choice. It doesn't take much to reach out.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Quote: It doesn't take much to reach out.
Now why would I want to do that?
|
|
|
|
|
|
Frequently when I generate code, I require a LOT of state. This, I've found, is the nature of code generation. You just have to keep track of sometimes over a dozen things at once.
I also tend to find that it lends itself to procedural style coding, rather than OO coding - not the generated code mind you, but the process of generating it.
The problem is, this results in an anti-pattern wherein I'm constantly passing at least 6 parameters per method.
Now, I could keep state in a struct and pass that around but the trouble is, those 6 (or more) different parameters - what they are - varies wildly depending on what I'm calling.
Again, the problem is the amount and variation of state I must work with at any given time.
Creating a bunch of types (classes or structs) just to hold it increases maintenance.
I don't have much of a problem reading the code. It's just the pattern crops up and I don't like it.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
Have you tried the obvious?
Have one "state" class that aggregates the entire state for the current parsing tree. Each method gets a pointer to this state, and extracts (or modifies) the necessary stuff from (in) it.
Admittedly, this is one level up from putting everything in global variables ( ), but if your state is used globally, it should be available globally.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
unfortunately a lot of it is not used globally, but manufactured inside loop bodies which then delegate to methods.
I could store whole arrays in there, but i've already processed that information, and I'd need to just process it again, so that's code in two places.
I do actually use the pattern you talk about elsewhere in my project, to good effect. I just don't think it will be effective here. That's not to knock your suggestion in general. Just you haven't seen this code, so you're flying blind as it were in this case.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
It's hard to answer this without looking at your code, and I haven't used C# and the other things that you write about.
I also don't know what you mean by procedural vs OO. OO still has procedures, but ideally they're small, with many being private or protected. If you're saying that your code looks more like a C free-for-all than C++, my guess is that you haven't yet found a division of responsibilities that yields good encapsulation. And it might just be that there isn't one.
I also don't know what the "input" to your code generator is. When I parse C++ to do static analysis, I also "execute" it using operand and operator stacks, which can emit a sort of stack machine pseudo-code to verify that the code was properly understood. My guess is that it wouldn't be difficult, although lots of work, to turn this into (inefficient) machine code. But this isn't at the same level of abstraction as generating class definitions, like you are.
You say that you can read your code easily, so it doesn't much matter if you think you'd still be able to pick it up again, with modest effort, in a year. If this is the first time you're doing code generation, be patient. Soon you'll probably have an epiphany about how it should be structured, presenting you with the painful choice between leaving it alone and doing a big refactoring!
|
|
|
|
|
Greg Utas wrote: my guess is that you haven't yet found a division of responsibilities that yields good encapsulation. And it might just be that there isn't one.
Yes to this. I'd divide the labor more, but again, the variation and amount of state involved in the generation process makes that so cumbersome as to be more trouble than it solves.
Greg Utas wrote: When I parse C++ to do static analysis, I also "execute" it using operand and operator stacks, which can emit a sort of stack machine pseudo-code to verify that the code was properly understood.
Slang does something very similar. It has to go and turn a parse tree into an abstract syntax tree of code using type resolution. That requires some level of evaluation. For example, I have a routine called GetTypeOfExpression(expr) that lets you retrieve the type of any expression you get, including method return values, and such.
Because of metadata I don't have to evaluate as much as you do. I just have to find types. All of that is nicely encapsulated in CodeDomResolver and CodeDomBinder. Still, it makes Slang take awhile to process.
But I use those ASTs when I go to generate code. I modify them, a pick parts out of them (for reasons - maintainability elsewhere- this allows me to "template" parts of the code)
And I also use things like parse tables.
I've been generating code for decades. It's kind of my thing. The code i generate has come from more and more complex sources.
It's why I'm generating a backtracking parser with syntax directed actions and semantic constraints in a language independent manner right now.
It's very challenging. For both me and my CPU!
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
Another way I confirm that the C++ code was properly understood is to regenerate it. The comments have been stripped out, and class members aren't in their original order, but the functions are there (with the type for each auto variable, to make sure it got that right). The code is regenerated by one or more Display methods on each object in the parse tree, which turned out to be much easier than I had anticipated. Just in case this helps...
|
|
|
|
|
I'm doing the exact same thing in slang to the same effect, with reordered members and everything. I even resolve var (the C# equiv of auto) to their appropriate types.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
Adding, right now my show stopping problem is my inability to factor a grammar for C#.
I'm running into problems with ambiguities between a cast and a parenthesized expression, but no matter how i apply semantic constraints i can't seem to resolve the conflicts. Plus it says my grammar is directly left recursive and i can't figure out why it would be.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
Too theoretical! I just wrote the parser without using any tools. C++ probably doesn't even have a proper grammar!
But I might get theoretical too, if I was trying to support multiple languages.
Parentheses were also one of my problems:
bool Parser::HandleParentheses(ExprPtr& expr)
{
auto back = expr->Back();
if((back != nullptr) && (back->Type() == Cxx::QualName))
{
TokenPtr call;
if(GetArgList(call))
{
expr->AddItem(call);
return true;
}
}
if(GetCast(expr)) return true;
return GetPrecedence(expr);
}
|
|
|
|
|
I already do that in my hand written parser
CodeExpression expr = null;
var pc2 = pc.GetLookAhead();
pc2.EnsureStarted();
try
{
expr = _ParseCast(pc2);
}
catch { }
if(null!=expr)
{
return _ParseCast(pc);
} else
{
try
{
if (!pc.Advance())
_Error("Unterminated cast or subexpression", pc.Current);
expr=_ParseExpression(pc);
_SkipComments(pc);
if(ST.rparen!=pc.SymbolId)
_Error("Invalid cast or subexpression", pc.Current);
pc.Advance();
return expr;
}
catch(Exception eex)
{
throw eex;
}
}
Ironically that TODO: is already handled by my generated parser (it counts tokens and dumps lookahead) but the above works.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
Have you tried using local function?
Just an idea!
|
|
|
|
|
There's an idea. I have not. I haven't really messed with them yet, though I wonder if I should use the newest language features or not. I like to stay a generation or two back with my codebase so it can compile for more people.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
Mm... I like to mess up with new feature as soon they come out... so that I get comfy with them!
And, on the particular case of local function I like them because I don't like to have a method that is used only by another method.. over time and refactoring its origin and purpose might get obscured and funny thing might start to happen... like dead code, or people reusing what should have been a private method, that get changed and broke everything...
|
|
|
|
|
Yeah, I can see that. For now I just distinguish by putting private in front of my one caller private methods. I leave them blank for other private methods.
The exception is with slang. I explicitly qualify members of types in C# code i feed it with access modifiers because VB demands it.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
One state one class, especially in case code is generated
It does not solve my Problem, but it answers my question
modified 19-Jan-21 21:04pm.
|
|
|
|