« first day (1899 days earlier)      last day (36 days later) » 

12:01 AM
[Phrancis/TwitterTools] 1 commit. 13 additions.
[rubberduck-vba/Rubberduck] 3 issue comments.
[Minesweeper] Games Played: 94, Bombs Used: 55, Moves Performed: 13031, New Users: 12
3 hours later…
2:39 AM
When at a funeral just keep smiling
2 hours later…
4:14 AM
Q: VBA loop optimization

Ed LandauHi folks: I posted a SO (https://stackoverflow.com/questions/57541246/optimizing-vba-function-loop) and was told to ask here. I am starting to think that rather than relay on excel as my data repository, I should create a separate class that holds a variant array that I can then query must fast...

8 hours later…
12:06 PM
Welp, I managed to write an unit test that passes in VS runner, but fails in Resharper's runner. If I fix it to pass Reshaper, it fails when running with VS.
12:28 PM
I really hate floating numbers. They only serve to incite pains.
12:40 PM
@this How is that possible?
This is the case:
[TestCase(-0.0d, typeof(string), ExpectedResult = "0")]
VS runner says it's 0. Resharper says it's "-0"
It's all about how you interpret the special case of -0.0d, which is not the same as 0.0d
Correction - VS runner says it's "0"
Why programs ever accepted the concept of -0 is beyond me.
12:56 PM
28 mins ago, by this
I really hate floating numbers. They only serve to incite pains.
1:10 PM
@Mast because IEEE floating standard
and because a / -0 != a / 0
Oh, -0 came as part of that?
@Vogel612 Last I checked you weren't supposed to do / 0 anyway.
yea, but it's defined in the IEEE fp standard
mostly to be able to account for nonsense like dividing by something smaller than the datatype resolution
1:33 PM
The problem, though is that you are relying on everyone else to implement the standard correctly.
Heh, are standards ever implemented correctly? There's always a tiny exception here, a small edge case there.
Can anybody think of a case where Let coercion kicks not in the following list of test setups, except for the LHS of a let assignment?
[TestCase("    Foo = cls.Baz", 11, 18)]
[TestCase("    Foo = cls.Baz + 42", 11, 18)]
[TestCase("    Foo = cls.Baz - 42", 11, 18)]
[TestCase("    Foo = cls.Baz * 42", 11, 18)]
[TestCase("    Foo = cls.Baz ^ 42", 11, 18)]
[TestCase("    Foo = cls.Baz \\\\ 42", 11, 18)]
[TestCase("    Foo = cls.Baz Mod 42", 11, 18)]
[TestCase("    Foo = cls.Baz & \" sheep\"", 11, 18)]
[TestCase("    Foo = cls.Baz And 42", 11, 18)]
[TestCase("    Foo = cls.Baz Or 42", 11, 18)]
[TestCase("    Foo = cls.Baz Xor 42", 11, 18)]
The Let coercion is on cls.Baz.
Thought of two more: if statement and one line if statement.
OMG, how many different things in the grammar use expressions?
I have nerver heard of half of them.
E.g. the seek statement.
I bet we miss a few when resolving identifier references.
2:18 PM
VBA, why do you have to support >= and =>?
not sure this makes sense: [TestCase(" Foo = cls.Baz Like 42", 11, 18)]
It is syntactically sound.
Like is an operator on string, so it's implicitly Like "42", no?
I can use something else, though.
I think that's good to cover different cases of Like
not sure that affects the resolver in the test, though
I don't recall off the hand if the For i = 0 to 1 is considered an expression.
2:22 PM
I have added a few more test cases:
[TestCase("    If cls.Baz Then Foo = 42", 8, 15)]
[TestCase("    If cls.Baz Then \r\n        Foo = 42 \r\n    End If", 8, 15)]
[TestCase("    If False Then : ElseIf cls.Baz Then\r\n        Foo = 42 \r\n    End If", 28, 35)]
[TestCase("    Do While cls.Baz\r\n        Foo = 42 \r\n    Loop", 14, 21)]
[TestCase("    Do Until cls.Baz\r\n        Foo = 42 \r\n    Loop", 14, 21)]
[TestCase("    Do : Foo = 42 :  Loop While cls.Baz", 33, 40)]
[TestCase("    Do : Foo = 42 :  Loop Until cls.Baz", 33, 40)]
Yes, both 0 and 1 can be an expression there.
very good
This is really a bit tedious.
There are so many places requiring Let coercion.
I know what you mean. But otherwise, we'll never get resolver right if we don't cover all cases.
WTF, who would ever use On <expression> GoTo <statement-label-list>?
That's a ThunderCode right there.
2:29 PM
It also exists with GoSub.
that was probably used as something akin to a jump table, I think.
Obviously, there are better ways but....
I guess it is there because of historical reasons.
I'm wondering, have you noticed VS test runner stopping working after few iterations?
2:48 PM
I guess, it does not hurt if we reolve a defaukt member access even, if the statement is not legal, right?
I am not too sure how strictly the Mid statement is implemented to spec.
It should be illegal, if the declared type is not String or Variant.
However, testing whether that actually holds would be a bit tedious.
3:26 PM
@M.Doerner Does it do exactly the same thing, as in, one is synonymous to the other? If that's so, no point writing 2 tests for it.
FWIW >< is supported in the spec, but the VBE autocorrects it to <>, so it's kind of an edge case
I wonder if there's a case where malware bypasses the VBIDE and save the "valid" VBA into the stream directly which might obscure the payload.
By the time malware can do that, don't you have bigger problems?
Possibly. I know very little beyond the fact that a common trend is to try and obscure the VBA payload
AIUI, they actually do very little in VBA; they just shell out to something else but they have to obfuscate the script that they execute via Shell or equivalent.
Since the VBE autocorrects it, it should generate the same p-code.
After all, what you see in the VBE is a reconstruction of the source code base on the p-code.
3:40 PM
yeah, true.
I guess, I should also add tests for expressions that should not be Let coerced.
and we can see why Roslyn would need tens of thousands tests.
Compilers for decantly expressive languages have tons and tons of cases to test.
VBA may not be as expressive, but it'll still need much more, possibly just as many because of all the weak typing and implicit conversion voodoo that goes on
I would definitly count VBA as decently expressive.
4:34 PM
I think I have all the necessary tests to verify that we resolve default member calls due to Let coercion; we have 144 of them now.
As an exception, I will make a commit with the failing tests and get them to pass over the next commits.
I have the feeling that making them pass will uncover a few more issues.
2 hours later…
6:14 PM
just checking --- would you consider this smelly code? Keep in mind I cannot do DI in this context because this class get created by VBA caller indirectly:
        private readonly ComMocked mocked;
        private readonly SetupArgumentResolver _resolver;
        private readonly SetupExpressionBuilder _builder;

        public ComMock(Mock mock, Type type, IEnumerable<Type> supportedInterfaces)
            Mock = mock;
            _resolver = new SetupArgumentResolver();
            _builder = new SetupExpressionBuilder(type, supportedInterfaces, _resolver);

            Mock.As<IComMocked>().Setup(x => x.Mock).Returns(this);
            mocked = new ComMocked(this, supportedInterfaces);
note that the type and supportedInterfaces are simply forwarded to the resolver which the ComMock creates for its use.
7:54 PM
Had a brain tickle regarding the settings windows. IIRC we have OK and Cancel. Would it be better to change OK to Save since changed settings won’t be persisted otherwise. Makes me think of following the principle of least surprise.
Hm. To me "ok" says "accept changes and close" when there's also a "cancel" button that says "ignore changes and close".. no?
@this makes me wonder whether Excel.Range might have that somewhere
@this why would it smell?
the newing up can't be avoided, that code is an entry point, the root of a dependency tree
lest the VBA code is in charge of providing the factories
@this wait so it's not always a default member call??
8:47 PM
@IvenBach "save & close" would be more explicit, yeah
Dictionary access expressions are a shorthand for a default member call; that is in the spec.
9:25 PM
Is it OK, if I assume that the code actually works in the default member resolution?
@MathieuGuindon it's actually not the root; it's one level down from the root (MockProvider). I suppose the MockProvider could have provided the factory or created the resolved directly and pass it into ComMock class - it's more that I want to keep the dependency graph shallow as possible since I have no DI.
@MathieuGuindon I think it is always - the attribute simply helps with optimizing - I assume to bypass the EnumVARIANT enumeration or something, IDK.
Hm, when we set the default member for a class with a Property Get and a Property Let, which one do we use?
Though the example in the article really doesn't make sense.
@M.Doerner I can't see how it work on only one but not other.
For the LHS of a Let statement, I basically need to recurse Get or Function default mebers until I find a Let default member.
We assign one declaration.
Get and Let are separate declarations.
i'm pretty sure from COM's POV they are one thing
9:31 PM
I guess, I will just assume I found the right one if I either find a Get or Function of a value type without parameters or a Let with one parameter.
I think, we assign the Get, unless there only is a Let.
Hmm. the spec is ambiguous on that point.
Seems like there are separater Get and Let default members.
note that they'd have the same names
which is why you must provide the kind
I guess it is OK not to check whether the default member is a subroutine. The code is illegal in that case anyway.
the dwFlags parameter is what help us determine whether to call a let or get or method
if you wanted to know how to invoke a get, it has a diagram. The next one is for let.
9:41 PM
Well, I already know whet we want to invoke. The problem is just to find the default member.
No, I was answering the question about whether COM sees property let / get as two or one members
and also trying to find if it specify what happens if the disp id isn't the same. I do not think it is possible to have 2 different disp IDs for a let / get
9:52 PM
> midl\oleaut32.dll : error MIDL2020 : error generating type library : SetFuncAndParamNames failed : get_Item (0x8002802C)
That is what I get if I try to set disp id differently
So, my method to look both for a Get and Let is probably what we have to do.
i'm trying to build a type library with only one set on either and seeing
We have the situation for user defined default members, if there is only a Let.
Works the other way, too.
If neither has the disp id set, then it won't be default member, so having one on only either is enough, apparnetly. I bet the same is true for the set (propputref)
huh. The set apparently doesn't work.
@this question: is [id(0x0)] not valid?
10:05 PM
I just checked. the id(0x0) does work on the others.
besides, if midl cared, it'd have yelled at me.
The trouble, though is that while we can see that VBIDE's OB will pick up the default member from either Let/Get, it doesn't say whether it does so by checking both or whether that the ITypeInfo has the appropriate attribute set for all let/get/set.
10:17 PM
@this not sure if its been exploited, but it's definitely possible
Does anybody of you know what is a nameStmt?
wouldn't that refer to the Name statement?
e.g. Name x As y
Yes, but what does it do?
(which is one of worst named statement if you ask me....)
it renames a file
I could not find it in the spec.
10:19 PM
I'd think it'd be in the spec
It is not in th PDF.
i guess they forgot
That explains why it is the last one in the list in the parser.
I think a language should not have such statements. That is the job of some method in the standard library.
it is the same language that has file I/O and filesystem accesses as statements, after all.
I guess they weren't too concerned about separation of concerns back then.
They also rather belong in the standard library.
10:45 PM
In the lineSpecialFormStmt, which expressions can be objects?
Same question for circleSpecialForm, scaleSpecialForm and pSetSpecialForm.

« first day (1899 days earlier)      last day (36 days later) »