« first day (1595 days earlier)      last day (1585 days later) » 
00:00 - 19:0019:00 - 00:00

7:01 PM
@MathieuGuindon Read that article. Explanation about the delegate not needing to expose the type of the class that implements it helped.
I've got the idea down. Now I need to use them.
 
I'm a bit lost with the word salad here.... a delegate isn't a class, it's not implemented
it's a type, but that's where the resemblance with a class (or struct, or interface) ends
 
> Given that almost all the modules are host-agnostic (kudos!), it should be possible to ađd a .vbp and a new view to allow the same codebase to be compiled as a standalone executable. Bonus points for adding CI with unit tests :-)
 
@Duga wanted to self-assign, but no rights :-(
 
> Think of delegates as describing the signature of only one method!
 
7:07 PM
@mansellan try that again?
 
I used the word class incorrectly then.
 
/s/class/delegate does make sense
if the return type and parameter types+order matches that of the delegate, then it can be passed as that delegate
 
@MathieuGuindon still seems not, but on mobile atm (tried the desktop view). I can confirm when I get home in a bit.
 
@IvenBach all the delegate promises is basically "I'm a function that returns X type and may/will require X parameter(s)".
 
That part I'm good with.
 
7:12 PM
It tells you nothing about the implementation of the function, akin to an interface
 
^ I never thought of it as that before.
That was the comment I was trying to make.
 
so I guess you could analogize it as interface => class while delegate => method
and because of that, you can hide the details behind the method's implementation (e.g. you don't need to know that it's defined in class Y to invoke it; you only need to be able to assign that method to the delegate, then forward the delegate to whoever else needs it.
 
struct is a kind of type that describes a value. class is a kind of type that describes an object. interface is a kind of type that describes.. er, well the interface of an object. delegate is a kind of type that describes a method's signature (whether that method is statically defined or compiled on-the-fly).
a delegate can be defined directly inside a namespace
 
^ that bit was a huge stumbling block for me and made me learn more about the function pointers to grok.
tbh, it's really nice to have a delegate type. In VBA, when you defined a callback procedure, you better have gotten the signature exactly right before you let the Win32 API call it back or you end up with a flaming poop bag
 
@this unrelated T-SQL quickie: I have table Foo with OtherFooId and Qty columns; I need to select foo1.Qty+foo2.Qty for both foo1 and foo2, but foo1.OtherFooId is foo2.Id and foo2.OtherFooId is null. Is that feasible with a single, incestuously spaghettish query?
 
7:20 PM
Interestingly, in F#, you don't have interfaces. You have types that contain functions.
So, you need a different collection of functions? Just create a new instance of that type with different functions.
 
ATM I'm able to get foo2 to correctly sum up the two quantities, but can't wrap my head around mapping foo1 back to foo2
i.e. I got the "links to ID" part easy, and now I need an easy way to figure out the "linked from ID" part of it (assuming 1 matching ID / level is fine)
 
It's a 1x1 map?
 
is this one level deep?
 
or can it go several levels deep? (e.g. it's an adjacency list)
Ok, good
 
7:24 PM
Just do (select [Qty] from Foo1 f where f.OtherFooId = Id) [Foo1Qty].
A nested query in the select.
 
That only works if its a 1x1 map.
 
no OtherFoodId will be null there, I already got that join down
 
Like that, I mean.
Or, if that's backwards, just swap it.
 
just so I'm not missing something basic - why wouldn't this suffice:
 
7:26 PM
One of them will be null, but the other won't.
 
SELECT
  foo1.Id,
  foo1.Qty + ISNULL(foo2.Qty, 0)
FROM Foo As foo1
LEFT JOIN Foo AS foo2
  ON foo1.OtherFooId = foo2.Id
 
because I need to return the same total qty for both records
 
So, you grab the non-null one and the non-null-matching-from-other-table one.
And compare them and grab the value.
 
I think window functions will work there.
 
@IvenBach I think part of the headache is that this bit of .net has seen constant change.... .c# 1 had delegates. .c# 2 added anonymous functions. C# 3 added lambdas and method groups. So you're trying to grok something that has been continuously improved over time... codemag.com/article/0809081/From-Delegate-to-Lambda
 
7:27 PM
SELECT
foo1.Id,
SUM(foo1.Qty + foo2.Qty) OVER (PARTITION BY foo1.Id, foo1.OtherFooId ORDER BY foo1.Id)
FROM Foo As foo1
LEFT JOIN Foo AS foo2
ON foo1.OtherFooId = foo2.Id
 
@mansellan hence why Skeet's book is so awesome, you get the historical walk through :)
 
I think that will give you the same output for same records.
 
Can you clarify our comment github.com/rubberduck-vba/Rubberduck/pull/…? I don't know how to piece that with what I've learned.
Its my lack of understanding.
 
Note: ORDER BY might be unnecessary/not allowed.
But you do need the PARTITION BY to ensure that both records get the same SUM.
 
@this you are missing the condition foo2.OtherFooId IS NULL
That makes the problem asymmetric.
 
7:31 PM
Foo1    1.5    NULL
Foo2    51.5  1.5
^ currently getting this
I feel like I'm 75% there :)
 
just to be clear, you want....
 
Hang on a sec.
 
Foo1    51.5  1.5
Foo2    51.5  1.5
?
 
Foo1    51.5    NULL
Foo2    51.5    1.5
 
Right.
 
7:32 PM
assuming 50+1.5
 
I thought so - then the PARTITION BY is wrong.
try PARTITION BY foo1.OtherFooId first.
this might be still wrong due to null values in the OtherFooId but let's do it one step by step.
 
select f2.Qty + (select Qty from Foo2 f2 where f2.Id = f1.OtherId)
from Foo1 f1

select f1.Qty + f2.Qty
from Foo1 f1
inner join Foo2 f2 on f2.Id = f1.OtherId
There's your two queries. One with the non-null and a join, and the other with a nested query :)
 
has to work for the 99.99999% of the records that don't have an OtherFooId though :)
 
What do you mean by that?
 
7:36 PM
@MathieuGuindon in this case, if you use Hosch's method, divide and conquer using UNION ALL, one summing only w/o, and other summing for both.
more verbose SQL, though.
 
I think what he wants is the result of
SELECT
  foo1.Id,
  foo1.Qty + f002.Qty
FROM FooTable AS foo1
  INNER JOIN FooTable AS foo2
    ON foo1.OtherId = foo2.Id
      AND foo2.OtherId IS NULL
UNION ALL
SELECT
  foo2.Id,
  foo1.Qty + f002.Qty
FROM FooTable AS foo1
  INNER JOIN FooTable AS foo2
    ON foo1.OtherId = foo2.Id
      AND foo2.OtherId IS NULL

but without the UNION
 
I thought he was running one query against one table and needed the same result but a different query for the other table.
 
well it's a rather simplified "MCVE" :)
@M.Doerner both would be left joins, no?
 
Writing SQL in the chat window is painful.
 
7:39 PM
Just to confirm, did you remove the ORDER BY from the SUM window function expression?
 
Why?
 
because most records don't have the self-join
oh wait
damn I hate tables that join onto themselves
 
But than by your description the quantity is not defined.
I thought you only wanted the pairs where foo2.OtherId is null and foo1.OtherId = foo2.Id.
 
yeah no I have fabric inventory I'm pulling from one system, and I need to update another db's fabric inventory but counting "OtherId" inventory as one & the same, for both involved fabrics
brain's melting, need caffeine
bbl
 
If you join them, just coalesce the id on the missing side.
SELECT COALESCE(F2.OtherId, F1.Id) AS Id FROM Foo F1 LEFT JOIN Foo F2 ON F2.OtherId = F1.Id
^ Then work off the coalesced key.
 
7:49 PM
Hmm
 
for a little bit there was like... what the heck is coalesce
then i realized i never used it because i always used case statements for weird fields
like if i had to do error checking type stuff
 
I got the F2 and F1 backward in the ON clause for the join. meaningful identifiers
> I just rip code off the internet, and pray it works.
 
@MathieuGuindon hearin your requirements for the query makes me go what?
 
Finally, somebody who's straight about that...
 
8:04 PM
SELECT *
INTO #foo
FROM (VALUES
	(1, 2, 50),
	(2, NULL, 1.5)
) AS t(Id, OtherId, Qty);


SELECT
	f1.Id,
	f1.OtherId,
	SUM(f1.Qty + f2.Qty) OVER (PARTITION BY COALESCE(f1.OtherId, f1.Id)) AS CombinedQty,
	f1.Qty AS Qty1,
	f2.Qty AS Qty2
FROM #foo AS f1
LEFT JOIN #foo AS f2
	ON f1.OtherId = f2.Id;

DROP TABLE #foo;
Id	OtherId	CombinedQty	Qty1	Qty2
1	2	51.5	50.0	1.5
2	NULL	51.5	1.5	NULL
I am not 100% confident this is right, though because I only ahve 2 rows. This can be wrong easily but it shows it is possible.
BTW.... you know there's sqlfiddle, right?
Makes it much easier to share and test the result.
 
Is there a good reason why we have so many parser rules that can match an empty string?
 
not that I know of. that's thwarting SLL, is it?
 
No, but it is making the parse tree larger than it has to be.
 
I noticed a couple warnings about some implicit tokens, too
 
E.g. we make moduleAttributes mandatory in a lot of places in a module, but let is match an empty string. Instead we could make it optional and always match a non-empty string.
That is probably for optional moduleAttributes.
Oh, the implicit tokens are in the preprocessor.
I think it is still relying on some lexer rules that got removed.
 
8:12 PM
is it possible that removing the empty strings from rules will prevent SLL?
 
I do not think so, but looking at some of the rules matching an empty string, making the usage optional would be rather inconvenient, e.g. for block.
Btw, building takes ages, now.
 
now?
 
I think some code analyzers are running that take very long.
 
lol, longer than it did before
 
8:20 PM
About three times as long.
 
I suspect it's running Microsoft's analzyers in addition to our custom analyzers
 
I think so.
 
That's also why Vogel was seeing so many warnings that we normally do not see in prior version - but I know from my past attempt of running Microsoft code analysis, we get several warning.
 
I thought it was running the MS ones before. Or are there analyzers specific to the new version?
 
Maybe we should disable MS's, and make it an explicit action
 
8:22 PM
can we make MS analyzers only run on CI?
 
I'm not sure there are any MS analyzers that we would need. Even CA2000 do not work.
(rather, they don't work the way we need it to)
I'm sure it should be possible. It's a matter of jiggling the handle.
 
	with flattened as (
		select
			 [Master]=m.Id
			,[External]=isnull(ext.Id,(select Id from rzra.Materials where ExternalClothId=m.Id))
		from rzra.Materials m
		left join rzra.Materials ext on m.ExternalClothId = ext.Id
		where m.Id in(53612,52916,52985)
	)
Master	External
52916	53612
52985	NULL
53612	52916
bingo
now join the inventory figures
why is it not whining about a missing index on ExternalClothId though
 
@MathieuGuindon You might want to open an issue for the problem with the precompiler grammar.
 
@MathieuGuindon if it's not, it's because it thinks it doesn't need it. Maybe it's the In clause that thwarts the need for one for instance.
 
@M.Doerner will do when I have the actual warnings in front of me :)
@this yet if I create the index, it merrily uses it
 
8:34 PM
@MathieuGuindon well, someone at the PASS compared the missing index details to Clippy....
 
e.g. it might be able to tell there's some wrong but the advice it gives isn't always what you want
 
@IvenBach To understand what the parse tree, my suggestion from this morning (your yesterday night) to try to figure out what the parse tree for '@Folder("SomeFolder") looks like might still be a good idea. However, I you want to see a graphical solution, I can post an image of it.
 
I used t => t.startRule() because that's what I was assisted with. I'm trying with x => x.moduleDeclarations() and others just to try and figure out which one to use.
It's not the use of the delegate that's the problem currently. It's knowing what to use.
 
The things you can request are exactly the rules you find in the grammar.
 
8:38 PM
the answer to that is in the grammar itself :)
 
^ where in the grammar?
I'm nagging for assistance, sorry.
 
VBAParser.g4
 
RD.Parsing.Grammar -> VBAParser.g4
 
You have R#, right?
 
@M.Doerner At home, Yes. At work where I'm presently at, No.
 
8:39 PM
Since I have it, I competely forget about namespaces.
Ctrl+T for the win
 
^^^^^^^
 
:feels-left-out:
VBAParser.g4 is what defines things for antlr.
 
Ctrl+T is FindAnything.
 
@IvenBach yes. and for every parser rule, antlr generates a class derived from ParserRuleContext
 
Yes, it is.
 
8:41 PM
..which implements... {drumroll} ...IParseTree
 
just to be sure --- so if in .g4 file you have a rule moduleAttribute, you get a ModuleAttributeContext... right?
 
The name of the class correspondin to a rule is <RuleName>Context.
 
I kicked appveyor to run a new build for #4441 which was failing due to the nuget server being unavailable
 
@M.Doerner :click: I think that was it.
Comparing this now.
 
8:43 PM
i wish that we didn't have to use eclipse just to view the parse tree live.
 
In addition to all the things from ParserRuleContext, these contexts have functions returning the results for subrules used to define the rule.
 
@this IntelliJ also has a plugin for that
 
Yeah. I did try that first, actually as I really wanted to avoid Eclipse so badly.
Unfortunately I could not get it to work.
 
If a subrule is not hit, the function corresponding returns null.
 
8:45 PM
@Duga #TIL - Thanks for the explanation.
 
We could also attempt to patch the generator to include a [DebuggerDisplay], which would allow examining the parse tree nodes properly
 
If it is hit, it contains the context for that subrule invocation.
If a subrule is potentially hit multiple times, the function will return an array of the contexts corresponding to the rule invocations in the order of invocation.
For any module remotely complicated, you really do not want to see the tree.
 
^^^
it's usually helpful only for one procedure
 
var result = VBACodeStringParser.Parse(sourceText, t => t.startRule());
var foo = VBACodeStringParser.Parse(sourceText, x => x.moduleDeclarations());
 
to help visualize how all rules fit together for a group of statements.
 
8:50 PM
The tree for '@Folder("SomeFolder") already has 30 nodes.
 
The invocation of parseTree.GetText() on each returns a different result for each.
 
@IvenBach it may help to keep in mind that each node is a nested set.
 
Nested set?
 
To oversimplify - for a statement If a = b Then, you have one node for the If statement, which contains 3 nodes; one for A, other for the =, and yet third for B
 
I guess foo was empty, right?
 
8:53 PM
The 3 nodes contained in the If node are representations of the left-of-comparison-operator, comparison operator, and right-of-comparison-operator respectively?
 
Well, it is a tree.
To be pedantic, it contains 5 nodes.
IF, whiteSpace, booleanExpression, whiteSpace, THEN
 
[rubberduck-vba/Rubberduck] build for commit c80cc17a on unknown branch: AppVeyor build succeeded
 
@M.Doerner Then the subsequent booleanExpression is a tree with 3 nodes?
 
It makes sense to think of it as 5 again. (Do not forget the whitespace.)
In our grammar, things are a bit more complicated.
 
I said nested sets primarily because of the fact all nodes will have an interval. You can tell how deep the node goes by the difference of the interval. (if that doesn't make sense, ignore me.)
 
8:59 PM
Ah, that was what you meant.
 
github.com/rubberduck-vba/Rubberduck/blob/next/… for the if statement, github.com/rubberduck-vba/Rubberduck/blob/next/… for the booleanExpression and each of those are subsequently composed of smaller parser "blocks".
 
but you're correct, a nested set is also a tree.
 
Yes, going down the tree, the code gets partitioned finer and finer.
 
Ultimately they are all defined in github.com/rubberduck-vba/Rubberduck/blob/next/….
 
Until you finally hit the tokens.
 
9:00 PM
What is the pedantic name for a "block"
Node?
 
It depends on how you look at it: if you look at it as part of the output structure, I would say node; if you look at it as part of the input, I would say interval.
 
Ok.
 
@IvenBach depends what "block" stands for?
 
I think he means the part matched by a rule.
 
c'mon... can I get a tiny break mug? I'm learning as fast as I can.
 
9:05 PM
ParserRuleContext then
or IParseTree
 
ifStmt :
    IF whiteSpace booleanExpression whiteSpace THEN endOfStatement
    block
    (statementLabelDefinition? whiteSpace? elseIfBlock)*
    (statementLabelDefinition? whiteSpace? elseBlock?)
    statementLabelDefinition? whiteSpace? END_IF
 
(we have a rule called block)
 
I'm trying to learn the simplistic IF whiteSpace booleanExpression whiteSpace THEN endOfStatement
In the example this gave If a = b Then
 
That might not be the best starting place.
Some of the rules in a If statement can devolve into expression parsing really quick.
 
9:08 PM
whenever you see something that's camelCase in the grammar, it's referring to another parser rule... which refers to another parser rule... {which refers to...} ..until everything is ALL-CAPS lexer tokens. so a "block" in the sense of a "VBA code block" (if..then..end if / for..next / etc.) is really not any different than a variable declaration statement, or any other parser rule: it's a lego block made with smaller lego blocks, made with smaller lego blocks, made with..
expression & friends is special though, because it's one of the recursive rules: an expression can be made of smaller expressions stitched together
 
What is the correct term for the lego blocks that make up the example If a = b Then?
 
That's what I meant by "devolve into expression parsing".
An If statement can be arbitrarily complex.
 
The booleanExpression a = b has 18 subrule invocations in total, i.e. the tree has 19 nodes.
 
The shape of parse tree for If a = b Then is also very different from the shape with If myCustomFunction() Then
I don't have the names off the cuff but the latter would use the rule for invoking a function / identifier.
 
9:12 PM
IIR a and b would be unrestrictedIdentifiers
 
/array index
 
...which is its own rabbit hole.
 
I'm oblivious to the recursive nature of lot if this stuff.
I'm going for a simple spoon-feedy-able example that blatantly ignores any complexity.
 
Dim foo As bar shouldn't recurse.
 
9:15 PM
And that's the tree you were referring to?
 
@M.Doerner What are you using for visualizations?
 
That is a = b.
The ANTLR 4 IDE 0.3.6 plugin for eclipse.
 
It is buggy like hell, though.
 
IKR?
 
9:16 PM
take note also that there are generalized forms. E.g. expression
 
Eclipse, or the plugin?
 
FWIW, if you're inclined to the path of installing the Eclipse.... someone wrote a wiki on how to get it set up.
@Comintern Eclipse is a bug
 
Why there is expression has a reason that would just confuse/side-track when explained.
 
Pretty sure I have Eclipse installed. I keep forgetting ANTLR isn't native to .NET.
 
You have to modify the grammar a little to actually work there.
The function names in the predicates have to follow the Java naming convention, i.e. start with a lower-case character.
 
9:18 PM
@M.Doerner agreed. For now it's enough to be aware that there are both specific and generalized rules, which may influence how your matching logic will work.
@M.Doerner fortunately, there aren't that many of them. Last time I did this, it was mainly changing the first letter's uppercase to lowercase, IIRC.
 
Generally, you want to define rules composed of multiple subrules or to go from more general to more specific.
However, there can be (techical) reasons why you have go from more specific to more general.
Btw, predicates are yet another concept not really relevant atm.
Looking at the parse tree visualization, I remember that there was some issue requesting to provide an export of the dependency structure of a project. I would really like to see that visualized for some of my projects.
 
9:34 PM
I might play around and see if I can get this running: github.com/mike-lischke/vscode-antlr4
 
Ooo nice. Even if it only works in VSC, I'd much rather use VSC than the abomination that is Eclipse
If you do get it, be sure to update that wiki. ;-)
 
Will do. I'm kind of curious about the call graph.
 
This seems to be an enhanced port of the ecplipse plugin.
At least it has basically the same visualizations, plus a lot more.
 
I'm just guessing it would be easier than dealing with my Eclipse install. I probably messed it up when I was configuring it for gcc anyway.
I know the gcc config is messed up...
 
10:25 PM
The right-click "Go to Definition" and "Peek Definition" alone make that VS Code extension worth its weight in gold.
 
Looks like I will have to install VSCode then.
 
This seriously makes viewing the grammar in Visual Studio proper seem like using Notepad.
 
It pretty much is
 
^
This is completely sick. Just need to figure out how to configure the debugger now.
 
funny timing - was just talking to a colleague about maybe trying out VSC at work. We're on a journey to move to Core (via netstandard) atm
 
10:48 PM
@Comintern Could you please update the wiki page for viewing the parse tree with when you have figured out how to configure the debugger?
 
Absolutely. I should probably take a few notes...
 
11:06 PM
@MathieuGuindon nope, still no rights to assign in Battleship
 
11:51 PM
Reading again Mugs grammar lessons specifically at chat.stackexchange.com/transcript/14929?m=35892777#35892777 to try and connect the dots of FooBarContext and what it contains.
Mar 8 '17 at 4:39, by Mat's Mug
module :
    endOfStatement
    moduleAttributes
    moduleHeader?
    moduleAttributes
    moduleConfig?
    moduleAttributes
    moduleDeclarations
    moduleAttributes
    moduleBody
    moduleAttributes
    // A module can consist of WS as well as line continuations only.
    whiteSpace?
;
I can do VBACodeStringParser.Parse(sourceText, t => t.startRule().module().moduleBody()); and the compiler allows me to do that since moduleBody is contained in module is contained in startRule.
 
Following that same logic I'm looking at using something which contains annotation>annotationList>commentOrAnnotation>endOfLine>...
 
@mansellan gah team was added... with read access. Fixed.
 
00:00 - 19:0019:00 - 00:00

« first day (1595 days earlier)      last day (1585 days later) »