« first day (1592 days earlier)      last day (1588 days later) » 

7:00 PM
or the same off of mercury
 
@this similar: cost can't be zero. ...until it needs to be.
@Comintern LOL
 
@MathieuGuindon do not share that with economists, though....
 
im getting to the point where i just dont know enough about how this module works that i am trying to update to even begin to try to do it right
i think im just going to rollback and just not touch this one till later
 
@this economists, no. marketing dept though...
 
7:13 PM
I'm trying to work out how to deal with folder annotation with or without a double quote.
 
@IvenBach I don't think you're supposed to. You need to get it from the parse tree. Do you have a parse tree?
 
are you not parsing it?
 
Does File.ReadAllLines count as parsing?
 
no
now you have a string - give it to the parser
 
Then I am ont.
 
7:15 PM
^^
 
give it to the parser, then you'll get a parse tree
 
File.ReadAllLines is to parsing as grocery shopping is to cooking.
 
1 hour ago, by this
https://github.com/rubberduck-vba/Rubberduck/blob/next/Rubberduck.Parsing/VBA/Pa‌​rsing/VBACodeStringParser.cs
I take it ^ is what I need to use.
 
yes
 
That's the stove.
 
7:17 PM
I'll try and figure out how to use this.
 
then you can make a visitor that drills down the declarations section and retrieves the annotation you're looking for - or returns null in which case you know you need to add it
or you can make a listener, but then you'll traverse the entire parse tree
 
I'd probably do a listener myself. This isn't a particularly hot code path.
 
@MathieuGuindon i may be mistaken but I think both traverses entire tree. The difference is in who drives the parse. Visitor get to drive, and thus can tell that everything is no-op whereas listener extend base's behavior.... AIUI but don't quote me.
 
5
A: Can a walker be stopped?

Sam HarwellYes, you can do either of the following: Throw an exception, such as a CancellationException Create a new class which extends ParseTreeWalker, and provide your own implementation of walk which understands the cancellation concept you need. It would make sense to start with the current implement...

 
:blub blub: I'm drowning in all the new stuff. Time to go down another rabbit hole to figure out how to do something basic.
 
7:21 PM
@this hmm, I thought a visitor put you in charge.. so when you want to bail out because you know what you need to know, you can just be done
 
Yes, that's correct
(forgot the cancelling bit)
 
@MathieuGuindon Dragon-glass!
 
@IvenBach It will make a lot more sense after you've looked through the parser contexts in a debugger.
 
How do I do that?
 
7:25 PM
^^
 
Set a breakpoint in an inspection that uses them, then play around in the locals window.
It will help if you have the grammar file open to decode specific contexts.
 
This is one of those "I'm lost badly" moments. I've set breakpoints inside the class on the Parse method but it's not firing.
 
the code string parser class?
or the main parser?
 
and is that what you're invoking?
what's your code doing?
 
7:33 PM
I don't know. I'm trying to have it pause on the parser to see what its doing as it's inspecting code.
I'm not having it pause on any code I'm writing.
 
RD isn't using the string parser
 
^
 
9 mins ago, by Comintern
@IvenBach It will make a lot more sense after you've looked through the parser contexts in a debugger.
I was trying to do that.
 
you need to new it up and call it, passing in the string.
 
and once inspections are running, parser has long completed
 
7:34 PM
Dealing with stuff I don't understand gets me lost easily.
 
@this not even, the method is static
 
One way to look at the parser contexts is to use the main parser, not the code string parser.
@MathieuGuindon bleh. #CaseOfMondays
 
Where's the main parser?
I couldn't figure out what to supply as the ParsertStartRule to have it parse the importing code.
 
var result = VBACodeStringParser.Parse(content, t => t.startRule);
 
Only reason the Inspections jumped out was because that's where I usually find myself looking at the raw parser contexts.
 
7:37 PM
^^ that gets you a (tree, rewriter) tuple
 
Note that you get a rewriter for free!
 
Wait... A return value can be two things?
 
no
there's one thing
 
it's like an anonymous struct
 
one tuple
 
7:38 PM
I'm at the junction of WTF and WTH right now. Bear with me.
4
 
LOL
 
that would be WTG I guess
 
I've read en.wikipedia.org/wiki/Tuple many times but can't grok what it is.
 
it's same thing conceptually as doing....
 
That's not the tuple you're looking for.
 
7:40 PM
wikipedia shouldn't be the go-to place for C# reference
 
@MathieuGuindon You're saying to use this to parse the code I provide it?
 
struct anonymous {
  IParseTree tree { get; }
  IModuleRewriter rewriter { get; }
}

anonymous Parse(...);
 
7:40 PM
it's actually a value tuple
a C# 7 thing
 
and calling it with var anonymous = thisClass.Parse(...);
 
look at the signature for the Parse method
the return type, more specifically
 
^ that's where your "anonymous struct" come from.
 
public static (IParseTree parseTree, TokenStreamRewriter rewriter) Parse(string code, ParserStartRule startRule, ParserMode mode = ParserMode.Default)
the return type is (IParseTree parseTree, TokenStreamRewriter rewriter)
 
And that's confusing as hell for me.
 
7:42 PM
it might as well have been a Tuple<IParseTree, TokenStreamRewriter>, but that syntax is annoying
 
^ and missing member names.
 
and then the tree would have been result.Item1 and the rewriter would have been result.Item2
 
I'd rather use a parseTree than an Item1.
 
I'm going to give myself an hour to read about tuple types. Hopefully that will let me take a step toward comprehension.
 
7:43 PM
it's just a generic type. Tuple<T1,T2,T3...Tn>
you create one with Tuple.Create(...enumerate your values...)
or if you're masochist, new Tuple<int, int, string, ...>(12, 43, "hi", ...)
 
Really, a Tuple the same thing as a struct basically; the only thing is that you don't declare a struct explicitly. It's all done inline.
 
117
A: What requirement was the tuple designed to solve?

Eric LippertWhen writing programs it is extremely common to want to logically group together a set of values which do not have sufficient commonality to justify making a class. Many programming languages allow you to logically group together a set of otherwise unrelated values without creating a type in o...

 
Hmmm... Is it better to put conditions in a JOIN's clause or in the WHERE?
SELECT * FROM Foo F JOIN Bar B ON F.Id = B.Id AND F.Baz = 42
or
SELECT * FROM Foo F JOIN Bar B ON F.Id = B.Id WHERE F.Baz = 42
 
> The concept of "group together a bunch of otherwise unrelated data in some structure that is more lightweight than a class" is useful in many, many places, not just for formal parameter lists of methods. It's useful when a method has two things to return, or when you want to key a dictionary off of two data rather than one, and so on.
@Comintern I'd put it in the join where makes no difference, really.
 
Yeah, that's what I usually do, but for some reason all the views in this DB are doing it on the JOIN.
 
7:49 PM
for the INNER JOIN there is no difference but there is a difference when it's OUTER JOIN.
I don't think whoever wrote that fully understood the subtle difference.
 
Because cartesian?
 
fewer rows to where on
 
a filter on ON is evaluated before the join; a filter on the WHERE is evaluated after the join.
 
but then, whether you do the work in the join or in the where, you do the work either way
 
Thus, this SQL doesn't work: SELECT ... FROM a LEFT JOIN b ON a.id = b.id WHERE b.foo = 'bar';
This is now an INNER JOIN because you've just excluded all null matches from the results, leaving you with only records for where there is a matching record in the b table.
 
7:51 PM
oh, duh
 
Right.
 
OTOH, SELECT .... FROM a LEFT JOIN b ON a.id = b.id AND b.foo = 'bar'; will get you all records from a and only those from b where foo is a certain value.
so..... a INNER JOIN b ON a.id = b.id AND b.foo = 'bar' makes zero sense.
and can be always refactored to a INNER JOIN b ON a.id = b.id WHERE b.foo = 'bar'
 
My favorite in this DB is foo f LEFT JOIN bar b ON f.Id = b.Id WHERE b.Id IS NOT NULL
 
I would prefer the latter because it's not equivocal.
wut
 
IKR?
 
7:55 PM
surely it was a brainfart? they deadtyped NOT where it shouldn't be, right?
 
I'm thinking not - it's in several places.
 
-_-
In that case, someone was sleeping during the SQL 101!
 
Probably there to prevent divisions by zero...
For n = 26 To 89
	'UserForm1.Controls("CheckBox" & n) = False
Next
O_O
Minesweeper?
 
step 1: scrap all the controls
step 2: make them dynamic redo the grid and quadruple-check the control names
 
I shudder to think of how long it must take to lay something like that out by hand.
 
8:06 PM
Ctrl+C/Ctrl+V is great for this
 
Not in the VBE - it piles them up on top of each other.
 
select 2, paste 2; select 4, paste 4; got 8; select 8, paste underneath, got 2 rows; select both, copy, paste, got 4 rows; select all, copy, paste, done - position each pasted group as you go
@Comintern yeah but it keeps them selected, so you can move them all together
#BeenThereDoneThat
 
Yeah. I guess after the first 50 or so, I'd start losing patience and ask myself why I wasn't using a control array.
 
"because VBA doesn't do control arrays" seems like a pretty good reason to me :)
VB6 has them though
 
You can do a wrapper class fairly easily though.
 
8:11 PM
@ticker is there a "post the worst possible SO question" contest going on or what?
@Comintern yes, but with the skill level of the OP you'd need one hell of a tutorial-grade answer to make that happen
 
Maybe it's the SO anniversary thing... They just hid it from anyone who follows the VBA tag.
 
@MathieuGuindon wishes nuggets were here already
 
so many missed opportunities in VBA...
 
8:36 PM
so, i never knew wtf a tuple was till i read this chat. thanks
 
I just read this evening's conversation. Why do you all want to reimplement the parsing and annotation discovery pipline, just to save the time it takes to resolve the references for a module?
@IvenBach You should definitly not use the VBACodeStringParser static class to parse modules to be imported.
It is lacking preprocessing.
 
@M.Doerner I shouldn't be allowed near the code I want to work on.
 
No
@this I just left the VBACodeStringParser as is because @MathieuGuindon was heavily using and changing it for its initial AC PR, which was still open when I did my refactoring.
 
@M.Doerner It's not just the time for resolving, it's that the module in question is not guaranteed to end up in the project until the import succeeds.
 
8:51 PM
@M.Doerner oh crap, completely forgot that
@M.Doerner block AC will still have to use it
 
@Comintern Now, I am confused. Why would I try to add a folder annotation to a module I cannot import?
@MathieuGuindon Inject an IStringParser.
 
@M.Doerner The idea was to test for the presence of a folder annotation in the text file, and add a default if it wasn't found. It's #4282.
 
will do!
 
@Comintern Thanks for the read. I have an idea of what Tuples are, why they are used, and enough knowledge about them to be dangerous to myself and others.
 
Why not import first and then and then change/add the folder annotation?
Basically, import folloved be MoveToFolder, which is also an outstanding issue.
 
8:57 PM
Wouldn't that flicker the UI though?
 
If you really parse the file, you will still have to find the folder annotation, which is not trivial because determining whether an annotation is a module annotation is not.
Flicker, no. It takes way too long to call it a flicker.
 
lol
 
More like, a few seconds.
 
@M.Doerner the worry was that import would cause a reparse
 
That is my point. Do the reparse, then you have everything at your disposal to make this very easy.
 
9:00 PM
then you have to re-parse
that's too expensive
the idea is to trivially parse, without resolving the module to get annotation, make edits, then import and parse/resolve once
 
If you do not want to reparse, you have to pase the module and do the processing to get the module annotations. Then you have write it to file again, followed by the actual import.
Resolving references for a single module does not take that long.
Well, unless you have a monster.
BTW, when adding a folder annotation, you have to be a bit cautious where you put it.
It might actually be prudent to always insert an empty line below it.
 
@M.Doerner no it doesn't; but with the main parser, it's a all or nothing deal.
 
BTW, the foreach in the import command is really wasteful.
 
@M.Doerner and this implies that we will use other method of locating the annotation which feels to me a bit too much re-inventing since we already solved the problem of finding annotations.
 
With the main parse it is, an all modified or new modules and the ones referencing them or no deal.
This command should really have the using around the foreach and do that in a suspend action.
 
9:18 PM
@MathieuGuindon How does t come about?
 
it's a delegate
t is the parser itself
public delegate IParseTree ParserStartRule(VBAParser parser);
var tree = startRule.Invoke(parser);
 
I'm still shaky with delegates. How does t => t.startRule() cause the ParserStartRule to be used?
 
1 min ago, by Mathieu Guindon
var tree = startRule.Invoke(parser);
follow execution into ParseInternal
 
@IvenBach So, this is how that goes :)
You know our parser .g4 file?
We have a rule in there named startRule.
 
it might as well have been a Func<VBAParser, IParserTree>
 
9:26 PM
That file gets parsed itself (probably with ANTLR!) and turned into a C# file.
So t.startRule() is really calling the parser startRule() method that we defined in our parser.
 
@Hosch250 I think he's more confused about where the t is coming from though
 
	[RuleVersion(0)]
	public StartRuleContext startRule() {
		StartRuleContext _localctx = new StartRuleContext(_ctx, State);
		EnterRule(_localctx, 0, RULE_startRule);
		try {
			EnterOuterAlt(_localctx, 1);
			{
			State = 456; module();
			State = 457; Match(Eof);
			}
		}
		catch (RecognitionException re) {
			_localctx.exception = re;
			_errHandler.ReportError(this, re);
			_errHandler.Recover(this, re);
		}
		finally {
			ExitRule();
		}
		return _localctx;
	}
 
Yeah, don't touch that :)
 
@IvenBach that's antlr-generated code, you want to look at the .g4 grammar file
 
That's all generated.
 
9:27 PM
@MathieuGuindon t is appearing out of nowhere, and I can't figure it out.
 
Hint--it's not really appearing out of nowhere.
 
To me it is.
 
It's just saying "I am a function that looks like returnType (argument)".
 
I can find where it's located in the grammar file easy enough: github.com/rubberduck-vba/Rubberduck/blob/next/…
 
So, let's expand that code:
 
9:29 PM
That is composed of the token module and EOF
 
not token
 
VBACodeStringParser.Parse(content, t => t.startRule);
 
tokens are lexer things
anyway the ParserStartRule delegate is a function that takes a VBAParser and returns an IParseTree. so when you provide the ParserStartRule you give it exactly that: a function that takes a VBAParser (that's t) and returns an IParseTree (that's .startRule().. it returns the parse tree for the entire module)
where t comes from is ultimately irrelevant, and only meaningful to the method that's using it
 
That is defined as:
public static (IParseTree parseTree, TokenStreamRewriter rewriter) Parse(string code, ParserStartRule startRule, ParserMode mode = ParserMode.Default)
A ParserStartRule is the interesting part:
public delegate IParseTree ParserStartRule(VBAParser parser);
So, there we are with our delegate.
 
I really should have made it a Func<VBAParser, IParseTree>
 
9:31 PM
That delegate is basically a function signature.
No implementation, just a signature.
And yes, it could have been a Func<VBAParser, IParseTree>, which is also a signature.
So now, what we can do is this:
 
private static IParseTree TheStartRule(VBAParser t)
{
    return t.StartRule();
}
 
Yes.
And now we can call VBACodeStringParser.Parse(content, TheStartRule);
And there's our function implementation.
 
because the signature matches the delegate
as does t => t.StartRule()
 
Except, C# has a handy way to define an inline function--a lambda.
 
Understanding that ParserStartRule takes in an argument of type VBAParser and returns an IParseTree is good. I understand that.
 
9:33 PM
t => t.StartRule() notation is pure functional programming, BTW.
Anyway, enough of that discussion.
 
instead of typing up a whole method body for it, you define the function inline, with a lambda
 
So, now we can define a lambda like so:
 
that's really all there is to it
 
(type t) =>
{
    //body
}
 
The lambda is designated by => and I can and do use it in simple examples.
I've never seen it used on multi-argument methods before.
 
9:35 PM
And the braces and parentheses are unnecessary if there is only one statement and one parameter, respectively.
So, a multi-argument method would do (t1, t2).
There are a few in RD here and there with Linq.
The C# type system can figure out the types mostly.
The type isn't necessary if it can figure it out.
 
Bear with me as I explain what I understand to try and illuminate what I'm missing.
 
IOW the fully fleshed-out lambda might be (VBAParser t) => t.StartRule() but that's redundant, because the Parse function already states that it wants a function that takes a VBAParser
 
You mean: (VBAParser t) => { return t.StartRule(); }
 
Notice that now it's literally just a function without a name.
 
9:39 PM
gosh see I couldn't be that redundant if I tried
 
VBACodeStringParser is a static class meaning you can't instantiate it, the same as with its method Parse. That's why VBACodeStringParser.Parse is used.
 
However, you don't need a name because it is never referenced--it is just passed around directly.
@IvenBach Yes.
 
reader is of type string[] which comes from var reader = File.ReadAllLines(filename);
 
Yeah. Although, I would think of it as an IEnumerable<string> because I don't know if it's an array offhand. No big difference either way.
 
I may or may not have it correct with reader.ToString() to concatenate/join it all back into a single string. That's not the part I'm stumbling over.
 
9:40 PM
That is wrong.
You do string.Join(Environment.NewLine, reader).
 
I'm fine hand wavey-ignoring it for now.
 
reader is a misleading name
 
That takes an IEnumerable<string> and concatenates them all together with the separator.
 
you're not getting a reader, you're getting the string content of the file
 
9:41 PM
the next argument is the t => t.startRule() which I can't figure out where it's coming from. How does it materialize or what causes it to do so?
 
It's a different notation for a function.
Before the => operator are the arguments.
After that operator is the body.
Most of the fluff has been cut away because C# can just figure it out.
 
the signature says "give me a function that takes a parser and returns an IParseTree"
implied: "I'll give it a parser when I want to invoke it"
 
So, in Parse, it has to call it like so: startRule(parser).
 
actually it's startRule.Invoke(parser);
#ExplicitInvokeFTW
 
Oh, yeah, because of the delegate.
 
9:44 PM
either works
 
Whatever. It's the same thing--just some funky binding stuff happening behind the scenes.
 
@Comintern Did you ignore any tests because of the cahcing issue?
 
Sheesh, I've just spent an extra 30 minutes at work :(
 
@Hosch250 you benevolent little slaveworker!
 
LOL, I was browsing SE and waiting for someone to get back to me.
I just told them I'd see them tomorrow, though, in our chat system.
 
9:46 PM
@M.Doerner No, the problem ones are in a WIP PR.
 
I won't record the time.
 
Everything before => are the arguments, and everything after is the body. I have that understood. I'm failing to see where t is coming from since Parse is a static method.
 
That comes from the Parse implementation.
 
t is part of the signature for the anonymous function
it's a parameter
 
9:48 PM
provided by Parse
25 mins ago, by Mathieu Guindon
1 min ago, by Mathieu Guindon
var tree = startRule.Invoke(parser);
 
var parser = new VBAParser(tokenStream);
return ParseInternal(ParserMode.Sll, parser, tokenStream, startRule);
var tree = startRule.Invoke(parser);
 
@MathieuGuindon Where is this line located?
 
So we create a parser.
 
Poke: has anyone beside this checked out the new csproj pr?
 
25 mins ago, by Mathieu Guindon
follow execution into ParseInternal
 
9:49 PM
Then we pass it into another method (ignorable, but whatever).
Then we tell it to execute the function startRule with the argument parser.
 
@Hosch250 Just to simplify a bit more...
public Foo(Action<int> bar)
{
  var i = 42;
  bar.Invoke(i);
}

...

myThing.Foo(t => Debug.Assert(t == 42);
 
@Vogel612 is it still WIP? I haven't yet.
 
^ aircode. May be boneheaded
@Vogel612 I have a quick look last Saturday, seemed good to me.
 
@this That would be an Action<int>, IIRC.
 
@MathieuGuindon no it's not, which is exactly the point of me asking
 
9:51 PM
:+1:
 
A Func<int> would be int().
An Action<int> would be a void(int).
 
@MathieuGuindon github.com/rubberduck-vba/Rubberduck/blob/next/… found that it exists. I can't get it through my head though how t => t.foo() does it though.
 
8 mins ago, by Mathieu Guindon
implied: "I'll give it a parser when I want to invoke it"
 
> Then we tell it to execute the function startRule with the argument parser.
 
:confused:
 
9:51 PM
Once again (it got buried):
We create a parser.
 
My VS install is just being a pain so the debug registration needs to be done manually
 
@IvenBach t => t.foo() doesn't invoke anything
 
We pass both values into another method.
 
it literally passes a function
 
Then we execute our function with the parser we just created as an argument.
 
9:52 PM
I think that's the disconnect. VBA can't do this.
 
^
I know VBA can't do delegates.
 
@IvenBach recall that this code is a bit dense because there's several layers between the calling function and the actual execution of the function definition. That's why I provided the simplified example above
 
here we're passing a function as a parameter - not its result
 
Don't worry, it took me months to learn this.
 
Where is the function coming from?
 
9:53 PM
if you know events, this is basically making events without creating event handlers.
from the calling code.
 
@IvenBach the lambda defines it
 
^
 
where does the lambda get it from?
 
from the called code. :)
 
9:53 PM
that's.. what lambdas do
 
It is not your lack of explanation. It's my inability to see the obvious.
 
No, this is the same problem I had.
Read about delegates first.
That splits it into function signatures and function implementations.
 
same problem everyone learning about delegates had.
 
I had the same headache when I first saw it.
 
9:54 PM
prepare to have the biggest OOOOOOH lightbulb moment of your life
 
Then one day, you'll realize that a lambda is basically a nameless function implementation.
 
^^^
 
#ItsNotJustMe
 
compare the docs with the simplified example provided earlier:
5 mins ago, by this
public Foo(Action<int> bar)
{
  var i = 42;
  bar.Invoke(i);
}

...

myThing.Foo(t => Debug.Assert(t == 42);
 
@Hosch250 I've had that realization on the simple stuff.
 
9:55 PM
int Function(string i)
{
    return i.Length;
}
Where does i come from?
 
When it's buried in with other complexities I get kicked in the face.
i is the parameter`.
 
exactly like t
 
int Function(string i) => i.Length;
C# 7 way of writing that ^.
So how close to a lambda that is?
Now let's say I take the int off--C# can figure that out.
 
you supply an argument to the parameter as in Console.WriteLine(Function(5));
 
And I take the Function off because instead of calling it directly, I'll pass it directly to someone else to call.
Then I take the string off--C# can figure that out.
What's left?
 
9:57 PM
suppose you have a method that goes public void DoSomething(Func<string,int> foo)
 
one sec...
 
you could do DoSomething(Function)
 
slow down
 
or you could do DoSomething(i => i.Length)
 
:wimper: too much knowledge. Brain can't hold it all yet.
 
9:58 PM
At that point we have (i) => i.Length, right? We don't have the int, the Function or the string.
 
@Hosch250 these simple lambdas I can do. Length is the member on string
 
And then we take the ( and ) off because we don't need them anymore.
Exactly!
 
docs.microsoft.com/en-us/dotnet/api/… and when you have int Function(string i) => i.Length; you're getting the length property.
 
So, in t => t.StartRule(), StartRule is a function on VBAParser.
Yes.
 
9:59 PM
@Hosch250 Let me try and find this, one sec.
 

« first day (1592 days earlier)      last day (1588 days later) »