quirks, possible bugs and a wish list

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

quirks, possible bugs and a wish list

02 May 2020, 23:12

My AHK knowledge might be superficial but Id like to share my impressions and expectations and point at AHK quirks, possible bugs and share some points of my wish list. :)
I pointed out some official docs errata and bugs in my previous topic
https://www.autohotkey.com/boards/viewtopic.php?f=37&t=74069&p=320060#p320060 where I mentioned one bug for v2-100 syntax scripts that forces AHK v2-108 to silently crash/quit at the pre-process stage.
Dont get me wrong - I do like the vector AHK2 progresses otherwise I wouldn't even start bothering to post. And sorry for my lame and sketchy language sometimes - I'm not a native English speaker. :) Ok, to the list:

1. AHK should give a pre-processor error if a static var is initialized more than once. The documentation says: Each static variable is initialized only once.
Ppl r prone to mistakes and leaving multiple initializations of the same var yields unexpected behavior (in the example below first h init. value is integer 0, second init. value is integer 123, it lets me re-initialize it within the first function call, and upon the second func call it SILENTLY resets to an uninitialized empty string ""):

Code: Select all

a ;Integer|123
a ;String|

a(){
        static t:=h:=0
        if(t)
		msgbox(Type(h) "|" h)
        else{
		t++
		h:=123 ;2nd initialization of a static var, it should give a pre-processor error here
		msgbox(Type(h) "|" h)
	}
}
2. BufferAlloc issue(?)

Code: Select all

     	t:=b:=h:=0
	DllCall("GetModuleHandle", "str","gdiplus", "PTR") || h:=DllCall("LoadLibrary", "str","gdiplus", "PTR")
	b:=BufferAlloc(16,0), NumPut(1,b,"UInt") ;GdiplusStartupInput struct
;initializes Windows GDI+:, 0=SUCCESS, 2=InvalidParameter:
	r:=DllCall("gdiplus\GdiplusStartup", "ptr*",t, "ptr",b, "ptr",0)
	msgbox r ;0=OK,2=ERROR
vs

Code: Select all

     	t:=b:=h:=0
	DllCall("GetModuleHandle", "str","gdiplus", "PTR") || h:=DllCall("LoadLibrary", "str","gdiplus", "PTR")
	VarSetCapacity(b, 16, 0), b:=Chr(1)
	r:=DllCall("gdiplus\GdiplusStartup", "ptr*",t, "ptr",&b, "ptr",0)
	msgbox r ;0=OK
Both variants create the same zero initialized 16 bytes long STRUCT with first byte overwritten with 01:
Clipboard01.png
Clipboard01.png (1.58 KiB) Viewed 988 times
BUT the first variant randomly gives me return code 2 (Invalid Parameter) for GdiplusStartup call. Second variant _never ever_ fails. Whats going on here? :(
Try to run both several times.

3. HasProp vs HasOwnProp: r there any difference? HasProp first appeared in v2-106. Now we got 2 different documentation pages:
obj.HasProp()
Returns true if the value has a property by this name, otherwise false
https://lexikos.github.io/v2/docs/objects/Any.htm#HasProp
vs
obj.HasOwnProp()
Returns true if the object owns a property by this name, otherwise false.
https://lexikos.github.io/v2/docs/objects/Object.htm#HasOwnProp

If Im not mistaken they seem to be the same if applied to user created objects/classes. I would prefer shorter variant then.
These *Own* methods spelling is too long to my liking, especially this one for dynamic properties GetOwnPropDesc - wow 14 letters. I would get rid of "Own" suffix at least.
GetProp -> DefineProp, GetMethod -> DefineMethod pairs seem to be more appropriate.
Enumerators could be reduced down to .Methods() and .Props(). s and () at their end hint that they r enumerators.

4. #warn for assume-local stuff yields: "This local variable has the same name as a global variable"

Code: Select all

#warn
class class1{
	static func1(){
		t:=1
	}
	static func2()=>(t:=2)
}

t:="A: not changed"
class1.func1() ;global var: "not changed"
msgbox(t)
t:="B: not changed"
class1.func2()
;v2-a108: OK, "not changed", METHOD and fat-arrow METHOD r assume-local!!
msgbox(t)
This warning for methods should be disabled.
Well, current AHK v2-108 still has the assume-global for fat-arrow functions. I cant fathom that quirk of using fat-arrows to initialize/change global vars. Its illogical and prone to mistakes.

5. After having read the AHK v2 subforum, I came across with Lexikos talking about BufferFrom(Ptr, Size) or similar command for memory range re-usage. Ofc this one would be very dangerous, possible to "Page faults" and other severe errors, but sometimes while working with huge memory arrays, re-usage instead of copying is a mater of life and death. Cant wait for such a command to be implemented.

6. Since v2-100, the latest v2-108 operates 2..25% as slow. It varies on OS and AHK functions used, but it is %10 as slow on average. the next code using AHK array manipulations is ended up being 26.6% as slow. I ran it with v2-100, v2-103 and v2-108 Unicode x64 AHK versions on Windows 10 x64. to run, just comment/uncomment lines with .length() respectively.
Spoiler
First ~5% slowdown can be seen at v2-102 -> v2-103 transition. I suppose its due to number of arguments passed run-time check. Good thing but but... AHK might do objects manipulation/loops 30-50 times as slow compared to mildly optimized C/C++ compiled code. these 5% translate into quite substantial slowdown overall.
Second major slowdown, another 5%, I haven't tested yet but I suppose, happened at v2-104's new objects paradigma shift.
I recall AHK2 gradually becoming more and more fast compared to AHK1.1 by removing all that irregular stuff like smart commas for msgbox and many other quirks.
Having strict syntax and more run-time check ups is a good thing, but I guess its time to pay some attention to AHK code optimization again. It should be like "tick-tock" for Intel, new design -> optimization cycles :)
Last edited by vvhitevvizard on 02 May 2020, 23:50, edited 2 times in total.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: quirks, possible bugs and a wish list

02 May 2020, 23:48

1) It gives error for duplicate static declarations / initialisations. Your code makes no sense in relation to what you have written, and probably does nothing related to what you think it does.
2) sizeof GdiplusStartupInput is 24 on 64 bit
3) yes there is a difference, hasown returns true if the object owns it, hasprop returns true if it or one of its bases owns it.
4) It works as it should. You need to understand the difference between assume local and force local, to begin with, I guess.

Cheers.
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: quirks, possible bugs and a wish list

02 May 2020, 23:58

1.
Helgef wrote:
02 May 2020, 23:48
1) It gives error for duplicate static declarations / initialisations. Your code makes no sense in relation to what you have written, and probably does nothing related to what you think it does.
Yeah there r no second static declaration with another static keyword otherwise I would get "declaration conflicts with existing var". But could u please explain why h var gets reset to String "" upon 2nd call? Shouldn't its value to be preserved between calls and be 123?

2. thank u for this quick answer! U saved my life!!! :D

3.
Helgef wrote: 3) yes there is a difference, hasown returns true if the object owns it, hasprop returns true if it or one of its bases owns it.
Ok got it! The documentation needs such details for sure. Its understood that work in progress just hoping to get there. Anyways the syntax is somewhat cumbersome. :D
Last edited by vvhitevvizard on 03 May 2020, 00:10, edited 1 time in total.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: quirks, possible bugs and a wish list

03 May 2020, 00:09

h is not static as you has not declared it as such. Non-static local variables are only cleared when a function returns, when the function returns, it clears the non-static local variable h. I wouldn't rely on the fact that you can reference a local variable in a static initialisation expression. Detecting it as an error would be more useful.

Cheers.
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: quirks, possible bugs and a wish list

03 May 2020, 00:15

@Helgef
Damn it. I used to think that a chained assignment with local keyword to the left declares all of them as local...

So in reality only the result of that expression returned (var t) declared as local. And indeed, static t:=0, h:=0 acts as expected. Thank u for explanation. ;)

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: akhiler, gsxr1300, songdg, william_ahk, wineguy, Xtra and 46 guests