Updated to v2-119. [list of 50 suggestions]

Discuss the future of the AutoHotkey language
User avatar
vvhitevvizard
Posts: 405
Joined: 25 Nov 2018, 10:15
Location: Russia

Updated to v2-119. [list of 50 suggestions]

26 Jun 2020, 07:29

07/08/2020: added #50. utilities I used throughout the topic r added to the 1st post
(hidden: stuff concerning v2-112 update)

AHK development shows great progress this year. I piled up a list of bugs/typos/my point of view suggestions accumulated recently. I prefer this format of keeping it all together in 1 updating post instead of creating multiple topics. The post will be revisited again and again by re-phrasing/clarifying the root of the problems, adding the community's opinions, removing the irrelevant and misleading stuff (errors happen quite often), adding more indicative short examples and half-way solutions, hiding resolved issues under spoilers and so on. Some of my points might be irrelevant (as proved by @Helgef, @swagfag, @nnnik, @lexikos) and I keep discarding them. :) Pls join that discussion and say what u think of some suggestions, add urs.
Most of my previous and following points propose command name's/syntax slight changes/addons/removals and focus on bringing more uniformity to the syntax: 5, 6, 13, 15, 25, 26, 27, 29
Some others concern debugging facility extension and seem to be not so hard to implement: 2, 3, 35, 36, 50. These, I believe, would greatly help with testing and debugging new alpha versions.
utils used throughout the topic
to collect and print out debugging info.
latest versions here


1. (brilliantly resolved in V2-114)

2. Ability to get global AHK vars (user and built-in) by enumerating them or something. And same for local ones. One step closer to managing namespaces.
e.g. listvars could take arguments and return some array or map instead of printing out in a window. Tbh, its current realization is totally useless for my taste: I can't use its output programmatically!
I recall in the past there were some hackery topics of patching AHK interpreter's binary code segment at runtime just to get these vars for further analyzing programmatically.
3. A_LineNumber, A_ThisFunc, A_LineFile, A_ThisLabel - to add similar command or expand the existing ones to expose callee's line number and function name (in other words, to expose calls' stack similar to exception()).
this would be very useful for debugging and logging purpose.
4. (resolved in V2-113)

5. Also it would be nice to have a shorthand for "background" keyword like "bg" or "b". Similar to "c" for "color".
Essentially, "background" and "section" r the only keywords that don't have a shorthand:

Code: Select all

;an array of options for gui.add (for its 2nd parameter)
["section background" b, "xs r1 w" w " background" b, "xs background" b, "xs r1  w" w " background" b]

6. (bug?) if an object has __Enum method, it should return something for for-in loop and don't throw. I found irregular behavior for Map's extension classes:

Code: Select all

class dbg{
}
class dbg2 extends Map{
}
msgbox("dbg.prototype.HasMethod('__Enum'):" dbg.prototype.HasMethod("__Enum")) ;0
msgbox("dbg2.prototype.HasMethod('__Enum'):" dbg2.prototype.HasMethod("__Enum")) ;1
for k,v in dbg2.prototype ;error: Type Mismatch
	msgbox("here")
The point is I just used a general recursive cycling thru all the exposed properties/nested objects of an object derived from Map.

Code: Select all

for k,v in (_o.hasmethod("__Enum") ? _o:_o.ownprops())
Function logic here is if something of built-in matter has __Enum then it can be enumerated via regular for k,v in obj and it SHOULD expose something w/o throwing. Otherwise we fall back to browsing thru obj's properties via for k,v in obj.ownprops().
7. File and some other built-in objects should expose more properties for an enumeration.
Usage? Self-logging script. File.pos, etc In the case of file. One could just do a general and simple for-in loop thru classes/global vars to save the current script's state. File object might be not the best example. But exposing as many properties as possible is not a bad thing for built-in objects.
8. (irrelevant)

9. Function to support Map creation.
To get the idea of what I mean, in an example we split a string with ";" and ":" delimiters:

Code: Select all

s:="
(
margin:1.0pt;
text-indent:8.5pt;
font-family:"Verdana";
)"

t:=Map(StrSplit(s, [";",":"])*) ;relatively slow 
;and throws run-time errors on empty array members corresponding to key-names instead of ignoring them..
;it should also left-trim/right-trim white space characters like \n\r\t for key-names.
Key idea is to speed up this basic map/str conversion functionality.
It should be a lot faster doing this with a new separate command like StrSplitM with native c++ code.
10. (resolved in V2-113)

11. (irrelevant)

12. local/global keywords for fat-arrow functions. In general it needs some vars declaration ability within an expression of fat-arrow. To be able to inline local vars usage. Right now I cannot use local variables inside fat-arrow function that declared at global scope.
So I have to resort to using a "hack" of allocating local vars in the args list, e.g.:

Code: Select all

gp_Pen(_c, _w){
	local h
	DllCall("gdiplus\GdipCreatePen1", 'uint',_c, 'float',_w, 'int',2, 'ptrP',h)
	return h
}
->

Code: Select all

;a fat-arrow function declaration outside class/function body:
gp_Pen(_c, _w, h:=0)=>(DllCall("gdiplus\GdipCreatePen1", 'uint',_c, 'float',_w, 'int',2, 'ptrP',h), h)
Or to make fat-arrow functions to be assume-local unconditionally. :)
13. NumGet to have a mode similar to NumPut "type1",output var1, "typeN",output varN ... address,offset. So it could automatically read multiple values by reading a value and changing the offset to the next one...

Code: Select all

r:={}, b:=bufferalloc(16)
r.x:=numget(b,0, 'float'), r.y:=numget(b,4, 'float'), r.w:=numget(b,8, 'float'), r.h:=numget(b,12, 'float')
->

Code: Select all

r:={}, b:=bufferalloc(16)
numget('float',r.x, 'float',r.y, 'float',r.w, 'float',r.h, b)

14. Recently I found this tendency of super-long keywords adoption. An average word in English is just 4.5 letters and computer languages go even further using some sort of abbreviations. For example, the majority of Basic's keywords is 3-5 letters long: dim, rnd, wend... Who knows, in the future AHK might get a command line interpreter mode like Python - the shorter keywords the better typing performance, and good stuff for inliners. :)
Recent updates have brought this monstrosity: varsetstrcapacity: 4 words 17 letters within 1 keyword, why so long? Why not SetStrCapacity, StrCapacity or something?
Another monster is GetOwnPropDesc. These Own* methods r too long to my liking, I would get rid of "Own" suffix. GetProp -> DefineProp, GetMethod -> DefineMethod pairs seem to be more appropriate.
And enumerators could be reduced down to .Methods() and .Props(): s and () at their end implies that they r enumerators.
15.
Further exploiting of .new method for built-in objects. Built-in objects system to be unified and consistent!.

fileopen -> file.new
bufferalloc -> buffer.new
maybe some cool syntax for StrSplit as well as long as it creates Array object. Array.FromStr() and Array.ToStr() (missing join, the opposite to StrSplit). :) And same for Map: Map.FromStr, Map.ToStr... U name it, I just brainstorming here
16. (resolved in V2-113)

17. 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. 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 matter of life and death.
Lets imagine, we have a huge memory region created not by AHK's BufferAlloc/File.RawRead or others. It might be an aftereffect of some external library call. We do have a pointer and we know a current size of that region and we want to use Buffer object facilities to control its boundaries and to tackle it using NumPut or other Buffer-aware functions. And we don't wanna waste CPU and memory resources by copying that memory region.
b:=BufferFrom(memory_addr, current_length) and voila! We've just reduced our carbon dioxide emission level! :D Cant wait for such a command to be implemented.
18. Preprocessor. Macro.
Why is this so important? Nowdays even assemblers or simple scripting languages like NSIS have an extensive preprocessor system. Google "ahk+preprocessor" https://www.google.com/search?sxsrf=ALe ... CAw&uact=5 - hundred requests - might be the most sought-after feature to be implemented.
in the simplest form,

Code: Select all

#define var_name

#if defined var_name
#else
#endif
would allow to have #include files cross-including each other w/o having troubles of multiple assignments/class definitions!
Also, having

Code: Select all

#macro
#endm
allows to have a brief and tidy code to be expanded into multiple AHK instructions at _load time_. Sometimes it performs dramatically faster than nested functions/closures/loops/etc.
All in all, preprocessor+macro is a language inside language with infinite posibilities and it won't hurt run-time performance.
19. loop keyword keyword keyword annoyance. Its so AHK1ish!
I recall a few alpha versions had LoopX commands coalesced: LoopParse, LoopFile etc. Loved it. Why? It facilitates code searching/replacing, it would allow loopsomething to be a function so one could insert it inside an expression...
20. Speaking of commands. Its cool to have function's call f() to be shorthanded to command syntax like the 2nd line in the example:

Code: Select all

f(a,b)=>a+b
f
but there is no opportunity to use remaining AHK commands as/in-place-of function calls or operators...
For example, let's look at the Python's loops inside square brackets: [f(x) for x in xs if condition]
to be expanded to
Python syntax is specific, but what I mean is having an ability to add loop, break, throw in expressions...
For readability, some ppl prefer each command to be on a separate line, but others would inline everything!
21. (not possible due to the existing line concatenation rule)

22. Refactoring... .exe compiler idea. NSIS is the only full-fledged script language competing with AHK by generating the smallest possible compiled standalone file: some standalone executable files could be as small as 25-40KB! Its done by separating interpreter's code into dlls and including only needed at "compile" time. NSIS script is not compiled into machine instructions or some pseudo-code, it remains in .exe as a source with removed var/subroutine names/comments/etc - same as AHK.
An example of NSIS compiled .exe's content (here we got some "built-in" and 3rd party libraries like 7z support):
Spoiler
I suppose like 1/3 of AHK .exe footprint is used by regexp lib_pcre, another quarter used by gui, 1/7 used by mouse functions, registry support... Imagine some compiled script not using this or that could be much much lighter in size.
23. Zero index for arrays. Recent versions made it mandatory to use indexing starting from 1. And [0] is an illegal index now. Alas, it does require additional work converting old scripts and worsens cross-language tasks. But also I do understand that having zero index reserved fits perfectly for many usage cases enabling the simplicity and power of boolean logic like in this case:

Code: Select all

h:="many words here!"
if(h~="word") ...
My point is to make sure then that all the remnants of zero indexing r not available by default.
Please remove Match[0] (equal to a whole found string). There is an alternative Match.len(0) anyways.
24. (bug) Concerning line continuation section start mark.
https://lexikos.github.io/v2/docs/Scripts.htm#continuation
If a line begins with a non-escaped open parenthesis ((), it is considered to be the start of a continuation section unless there is a closing parenthesis ()) on the same line.
That brings issues of mixing continuation section with expressions divided by continuation prefix:

Code: Select all

a:=1
(b(0
, 0)) && a:=2
In the above snippet one would expect Line 1 is completed and not connected to line 2,
Line 2 starts with an expression in parenthesis (function call with 2 args) and that expression's result used as 1st operand of && operator.
When a regular continuation section starts, it looks like

Code: Select all

Var := "
(
Line 1 of the text.
Line 2 of the text. By default, a linefeed (`n) is present between lines.
)"
so ( of a continuation section's start mark is a solo opening or closing parenthesis and not followed by a variable or operator or other stuff we expect to be within an expression.
The current state leads to the following preprocessor printout (the same behavior with AHK v2 builds 103,108,115):

Code: Select all

Error at line 1.
Line Text: a:=1, 0)) && a:=2
Error: missing ")"
WOW. In "Line Text" printout (b(0 disappeared! between lines 1 and 3. So AHK simply ignored leftovers that followed opening (. That's totally counter-intuitive.
another example
Request: In order to let lines starting with an expression to co-exist with continuation sections, start mark for the latter should be considered only when its a solo parenthesis on the line. And the closing section mark to be ) or )", )', )` respectively.
25. (resolved in v2-117)

26. Similar to 25, ability to test whether a gui control is "destroyed" w/o throwing.
27. Naming inconsistency. Some built-in functions use Len prefix, other properties have a Length moniker. e.g. StrLen, Match.Len() vs File.Length, Array.Length. For consistency, I would prefer unified Len everywhere.
28. Callback for regexreplace. So that it would be possible to exploit a custom function instead of replace argument's string pattern.
NB: Not to confuse Callback with the existing Callout debugging facility!
Real-world use of that functionality (regexf function). Example does decimal html entities -> unicode) conversion:

Code: Select all

s:="разобрат"
o:=str.regexf(s, '(?:&#(\d+);)', (_m)=>chr(_m[1]), c)
msgbox(s "`n->`n" o "`nReplaced <" c "> times")

class str{
	;RegExReplace with callback. _s:haystack, _q:needle, _f:replace func, _c:cnt
	static regexf(_s, _q, _f, byref _c:=unset){ 
		n:=1, s:="", c:=0
		while(i:=regexmatch(_s, _q, m, n))
			c++, s.=substr(_s, n, i-n) %_f%(m), n:=i+m.len(0)
		isset(c) && _c:=c
		return s substr(_s, n)
	}
}

29. Addition of FileWrite (symmetrical to FileRead). Well, or removal of FileRead, FileAppend. Commands set should be consistent: writes mirror reads.

Code: Select all

d:=fileopen(_s, "W"), n:=d.rawwrite(b), d.close()
->

Code: Select all

n:=FileWrite(b, "Raw")

30. When we assign a "text" to a gc control, AHK automatically measures its extents and resizes it accordingly. It would be logical when changing text style/etc to have the same auto-functionality. And ability to disable any autosizing at all like setting or not setting "AutoSize" attribute for gui.show().
Example (I used a snippet from a singlet class I use for miscellaneous gui utility functions). Uncomment 4th line:
text width auto-resizing example
BTW, C# has the following settings for gui controls:

Code: Select all

Button.AutoSize=true;
Button.AutoSizeMode=GrowAndShrink;
Button.TextAlign=Left;
Button.Padding=new Padding(0, 0, 0, 0);
etc
31. Continuation of the previous idea.
gui.add("text","xp xs+3 w45 cWhite") syntax might be handy for simple gui control layouts, but for complex ones one might wanna populate gui controls programmatically.
So having additional commands changing gc style similar to recently added gc.getpos(x,y,w,h) is reasonably necessary: gc.setpos(), gc.settextstyle( [bold/italic/other flags,size, kerning/etc]), gc.setcolor(color [,background]), gc.autosize, gc.settextalign(), gc.padding, gc.marginx, gc.marginy, etc.
IMHO, both "text string of params" and "set of methods" approaches could co-exist for a while until the former to be phased out.
32. Concerning another AHK's quirk mitigation: runtime checkup for a passed byref argument not being a variable. There is an existing IsByRef function already, but manually providing a checkup of every passed argument for being a not valid "expression" like obj.property is a pain.
Having an ability to enable/disable that check for all the byref arguments globally with 1 #warn directive would be great. If it doesn't dramatically hurt runtime performance ofc.
33. this one is a general observation concerning non-preprocessor directives system: some in form of #command, others in form of a_variable. No uniformity here.

Code: Select all

#SingleInstance force
#KeyHistory 0
a_listlines:=0, a_iconhidden:=1, a_fileencoding:="UTF-8"
;...
Due to preprocessor's stage 2 (or more?) passes, many language statements r put into effect before the script begins running (e.g. class declarations) and there is no principal difference between most of them - some r read-only, some r put into effect only once and before runtime, but there is no unified naming convention. For example, could #hotkeymodifiertimeout be a_hotkeymodifiertimeout? Or a_listlines be #listlines? I suppose, they were made this way due to AHK historically progressed by piling up more and more commands, written by different people, w/o actually following general design rules. Nowadays not having a unified system makes a learning curve more steep. Ideally, similar to other languages, only lexemes that active at the very first preprocessor's pass should have # prefix.
34.
my complaints got resolved by @swagfag
the only grumble left is obj.ownmethods to be extended in the future to additionally enumerate .base for methods so as to mirror (emulate) obj.ownprops mode.
35. Additional debug info. To let a script know of how much time (in milliseconds) pre-processing took. It might be A_LoadingTime built-in variable denoting a tick count of reaching WinMain() of AHK interpreter and preprocessor start, A_RunTime denoting a tick count of the beginning of script's run-time.

Code: Select all

msgbox("preprocessing took " A_LoadingTime-A_RunTime " ms")
It would be a good instrument for assessing the interpreter's and script's code preprocess-time optimizations within a script.
36. Alternative to A_TickCount returning microseconds. A_TickCountExt? A_McsCount?

Code: Select all

dllcall('QueryPerformanceCounter', 'int64P',c:=0)
and converting ticks to microseconds by:

Code: Select all

	ticks2mcs(_t){ ;perf counter ticks to mcs (microseconds)
;The freq of the perf counter is fixed at system boot and is consistent across all processors
;	We query it upon app init and cache
		static f:=0
;If the installed hardware supports a high-resolution perf counter, the retval is nonzero
		(f) || 	dllcall("QueryPerformanceFrequency", 'int64P',f)
;To guard against loss-of-precision, we convert to microseconds *before* dividing by ticks-per-second:
		return(_t*1000000/f)
	}
Every split microsecond matters: having this built-in would increase accuracy of measurements: see https://www.autohotkey.com/boards/viewtopic.php?p=344851#p344851
37. object.property use for dllcall.
a) working:

Code: Select all

dllcall("some_dll_function", 'ptr',obj.p:=0)
b) syntax allowed but not working (obj.p silently fails, does not receive the output value):

Code: Select all

dllcall("another_dll_function_receiving_pointer_to_a_pointer", 'ptrP',obj.p:=0)
The reasoning of that quirk is known: object.property, being an expression, cannot receive a value directly.
Could we have some preprocessor's latent propagation of additional commands: allocating a temporary_variable for .property and committing obj.p:=temporary_variable right after the function call:

Code: Select all

obj.p:=0
dllcall("dll_function", 'ptrp',obj.p)
at runtime translates into

Code: Select all

obj.p:=0
dllcall("dll_function", 'ptrp',tmpN)
obj.p:=tmpN
Before such an implementation, dllcall should flag an error for 'ptrP',obj.p.
38. a namespace management syntax ideas
PHP-like: declaring globals inside the included file as belonging to namespace utils:

Code: Select all

namespace utils{
#include utils.ahk2
}
so that every variable declared as global would become utils:variable (utils_variable, whatever) for AHK's inner logic. And it is totally transparent for the code inside namespace {} brackets with AHK transparently pre-pending namespace prefix to vars/classes declaration.
And the script code located outside utils.ahk2 to address those vars/classes/functions as utils.name (utils:name, etc)
Python-like:

Code: Select all

#from utils.ahk2 #import function_name #as fn
Declaring a namespace just for a function and also renaming it on the fly.
That would greatly help to resolve global var naming conflicts.
39. #requires
I can't apprehend what syntax is required to make some special script version run ONLY with the exact alpha version. I tried

Code: Select all

#Requires AutoHotkey v2.0-a103
But it still runs on V2-a116 w/o that special warning/error. The point is one might want an exact version to be defined, or the maximum version in addition to.
Request: ability to set a range, e.g. v2.0-a103, v2.0-a107 with comma or just whitespace between version numbers. E.g.:

Code: Select all

#requires AutoHotkey v2 ;doesnt work with AHK V1 or AHK V3, tries to run with any AHK V2 version
#requires AutoHotkey v2-a116 ;works with this exact AHK V2 version ONLY.
#requires AutoHotkey v2-a116 V2-a119 ;expects only this range of AHK versions.

40. Enumerators. One-parameter mode for array returns a value yet for map it returns a key.
NB: the majority seems to be against this change. But its my wishlist so I keep my reasoning here:

Code: Select all

a:=["aa","bb"]
b:=map("a","aa","b","bb")
for v in a
	msgbox(v)
for v in b
	msgbox(v)
For array enumerator to return value is quite convenient cuz key can be obtained via A_INDEX. It is expected that map would return value as well.
Was it made on purpose to differentiate array from map? In my opinion, both have similar access operator [] and this inconsistency with one-parameter for-loop might cause many unexpected issues. We just need a unified (expected) rule here.
So my try to bring it to consistency is to propose a 1-var for-loop to return a key (essentially only changing for k in array implementation (but not for k,v in array or both for-loop for map), it forces to use 2-vars instead of 1 for old for k in array behavior). It would make things plain simple and logical: 1-var for-loop returns keys always, 2-var for-loop returns keys,values.
The majority of script writers uses 2-vars mode anyways so the transition might be not so painful. It may be too late to change this behavior, or may be not - we have this opportunity while being in an alpha stage. Such quirks will be an eternal source of frustration.
alternative opinion (to let it as is):
@swagfag: it doesnt matter that its not consistent with Map - it doesn't have to be; a Map is a Map and an Array is an Array, theyre different data structures. In the future if more data structures are added, id want them to enumerate in a natural way that makes sense for them, not to satisfy an arbitrary constraint.

41. Variadic function/method vs (essentially) variadic syntax __call meta-function.
__call(_a*) returns array of argument(s) nested in another array (unexpected).
An agreement required: for all the functions/methods to have variadic syntax if they return a variable number of parameters. Also that
requires that old and future built-in functions to have variadic params* to be the last in the parameters list.
see more details

42.
Sometimes continuing to the next line is adequate, or just saves time during debugging (vs. editing and restarting the script to bypass a trivial error).
I experience an issue of not being able to exit the misbehaving script on a repeating continuable error "Target control not found". Try to continue anyway? I press No. It exits the thread then creates it anew and the same error pops up again and again... I'll add an example later.
Request: To add a third button (LOL) to exit all the threads and terminate the application.
43. Similar to #42, a button to unconditionally exit a parsing process (terminate AHK session) after the first warning dialogue at loading time. Quite often, the script writer just wants to stop repeated warnings and get back to editing.
44.
To stop a file that is currently playing, use SoundPlay on a nonexistent filename as in this example: SoundPlay "Nonexistent.avi".
And it throws:

Code: Select all

soundplay("-1")
I wrote that point after realizing wrapping it in try/catch block feels awkward:

Code: Select all

try soundplay("-1")
catch e{
}
And the whole routine of stopping the currently playing sound by starting to play again another non-existent sound file doesn't feel right at all.
Now that AHK discerns strings from pure numbers, it could be a pure number 0 (NULL, FALSE) as a soundplay first parameter to stop playing.
Also, I believe we might have another command to simply stop playing w/o throwing. soundstop() or similar.
@swagfag proposed a custom function:

Code: Select all

soundstop()=>dllcall('winmm\mciSendString', 'str','stop AHK_PlayMe', 'ptr',0, 'uint',0, 'ptr',0)
It would be great to have it on C++ AHK side eventually.
45. Having new load-time warning This var appears to never be assigned a value is absolutely amazing, but what about output variables like x,y,w,h in getpos(x,y,w,h)
One has to initialize them: getpos(x:=0,y:=0,w:=0,h:=0)
but these variables r used to retrieve values only and initialization is redundant here.
A preposition to add additional syntax keyword to declare output variables so as not to be checked for initialization/assignment.
thx to @iseahound, C# syntax looks pretty much relevant here: getpos(out x, out y, out w, out h)
C# out and ref keywords wrote: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-parameter-modifier
The out keyword causes arguments to be passed by reference. It is like the ref keyword, except that ref requires that the variable be initialized before it is passed.
My proposal is not to make out keyword mandatory, but to give a script writer 3 choices:
1. disable all warnings with #warn and have some output variables unassigned.
2. explicitly assign some values to them, e.g.: getpos(x:=0, y:=0)
3. do not assign any values but declare them as output variables: getpos(out x, out y)
Also it helps to memorize parameters' order.
@swagfag: If adding extra special operators(eg * ^ & out) would simplify the implementation/provide more robust error detection, go for it.
at the very least it would serve to better document outparam usage
Other syntax variants

46. Revolt! Revolt! the majority wants command syntax to be completely removed. Some ppl do like to use function calls w/o (). How about a compromise: #nocommands (#commands off, #syntax strict, whatever) pre-processor directive to disable command syntax (forcing to use () for function calls) in the script being parsed so that f (37,38) lines would finally trigger a warning or error.
Basically the major issue of command and function syntax co-existence is the general expectation that follows other languages (THE MAJORITY of them) design rule: a variable/object member's name with () following it executes the function/method with that name, a name w/o () is treated as a variable/object/pointer. And I can't help it - I keep shooting at my foot.
wrong expectation example
Also, var inside [explicit] expressions and outside them (after control flow statements, in the line beginning) processed differently and misleads even more:

Code: Select all

f 1 ;function's call
f ? 1:0 ;variable's access
(f 1) ;variable's access

f(*)=>msgbox()

47. abbreviations for dllcall parameters types. Similar to AHK_H V2 branch (by @HotKeyIt) with DllCall's equivalent named DynaCall.

Code: Select all

Int	i
Str	s
AStr	a
WStr	w
Short	h
Char	c
Float	f
Double	d
PTR	p
Int64	i64
PTRP	pp, etc
I expect some scripts extensively using dllcalls to be reduced to the extent of 2-10%.
example:

Code: Select all

gp_ellipsefill(g,b, x,y,w,h)=>dllcall("gdiplus\GdipFillEllipse", 'ptr',g, 'ptr',b, 'float',x, 'float',y, 'float',w, 'float',h)
->

Code: Select all

gp_ellipsefill(g,b, x,y,w,h)=>dllcall("gdiplus\GdipFillEllipse", 'p',g, 'p',b, 'f',x, 'f',y, 'f',w, 'f',h)
DllCall could actually support both notations - regular and abbreviated at the same time for compatibility sake.
48. (bug) Some control flow statements don't allow a space between a command and its expression: try(f.type) ;syntax error vs if(g) ;OK
Another inconsistency with control flow statements: if (expr)=if(expr), but return (expr) is not the same as return(expr).

Code: Select all

f:=1
if(f){ ;OK
}
if (f){ ;OK
}
e()

e(){
	f:=1
	return(f) ;call to non-existent function (unexpected)
	;return (f) ;OK
}
Addition to #48. In C, return (expr); vs return expr; vs return(expr);. Its dependent upon personal taste: all the three variants r legit.
  • Some coding guidelines consider using braces a bad practice, yet other stylistic conventions require them.
  • Whitespace (or space(s)/tab(s) at least) between non-literal symbols is optional.
  • Originally old convention C had parenthesis mandatory for returned values.
  • Parenthesis can be used to define return as a macro and then insert some logging code to trace all the return () statements.
The same goes for case, throw and probably some others.

back to AHK V2: we've got this inconsistency:

Code: Select all

try f ;f considered as a function call
return f ;f considered as a variable
Making parenthesis mandatory for every expression (condition, returned value) following a statement keyword: would it reduce the parser's complexity and increase performance?
49.
https://lexikos.github.io/v2/docs/commands/Trim.htm
Quote: Any string value or variable. Numbers are not supported.

Code: Select all

s:=7700.4 ;type=float
msgbox(ltrim(s,"7"))
output:

Code: Select all

00.3999999999996 ;type=string
So it silently converts a pure number (integer/float) into a string before trimming it.
Either the documentation needs to be updated to mention that behavior
Any string value or variable. Numbers are not supported. -> Any string/numeric value or variable.
or the command trim|ltrim|rtrim to be changed to throw ("expected a number but got a string" or something like that).
50.
Debugging facility. To add ObjRefs(obj) returning object's reference-counting to replace this undocumented object's data use with a built-in function:

Code: Select all

objrefs(_o)=>isobject(_o) ? numget(objptr(_o), 8, 'int64'):0 ;get obj ref counter
--------------------------
update notes
1. Please, always specify full function/method/property names b/c it has to be searchable:
Merged ControlGet/SetTab into ControlGet/ChooseIndex.
->
Merged ControlGetTab/ControlSetTab into ControlGetIndex/ControlChooseIndex.

Changed Group(De)Activate/Close to throw
->
Changed GroupActivate/GroupDeactivate/Close to throw
2. Implemented #Requires is skipped for v2-113 notes. :)
3. I feel like people r reluctant to upgrade. I know, for the developers, its hard to keep in mind and cover all the stuff in the update notes, but a workaround/replacement for removed/restricted/changed features should be provided whenever possible. E.g.: "for //, //= old behavior use floor(a/b)"
Having instructions of what exactly has to be replaced with what exactly in order to upgrade from previous version(s) would greatly motivate people upgrading.

--------------------------
documentation
There r lots of typos, I lost some notes so I recall only a few for now:
1. (fixed in the upcoming ver)
2. (fixed)
3. (fixed)
4. (fixed)
5. (fixed)

6.
https://lexikos.github.io/v2/docs/objects/Buffer.htm
Kinda redundant phrase :)
ClipboardAll returns a sub-type of Buffer, also named ClipboardAll.
7.
https://lexikos.github.io/v2/docs/objects/Map.htm
Recent built-in objects and functions definitely require more simple examples of usage in the documentation, like this one for Map (example by @Helgef):

Code: Select all

;create a map with a customizable default value:
class m extends map {
	__new(default := 0) => this.default := default
	__item[key] => this.has(key) ? base[key] : this.default
}

8. https://lexikos.github.io/v2/docs/Functions.htm#Local
Some "pay attention" warning in the documentation concerning local, global, static commands in conjunction with chaining assignments.
local a:=0, b:=0, c:=0 and local a:=b:=0, c:=0. The latter is not declaring all the 3 vars as local. Sometimes its easy to overlook...
9. (fixed)

10. (fixed)

11. 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
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
To add an explanation of the difference (by Helgef): HasOwnProp returns true if the object owns it, HasProp returns true if it or one of its bases owns it.
12. https://lexikos.github.io/v2/docs/Objects.htm#ObjPtr
The current object structure detailed explanation (offset/description) that might be very useful for ones trying to figure out how to organize an interface between compiled code and AHK objects.

Code: Select all

0	vTbl pointer
8	mRefCount
;...
etc. The format is changing and scripts using this "low-level" mechanics won't be compatible with other AHK versions but it won't be compatible with future alpha versions anyway... :) And AHK object's layout is changing not so fast, mainly via major updates only.
Last edited by vvhitevvizard on 07 Aug 2020, 10:37, edited 214 times in total.
User avatar
nnnik
Posts: 4470
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

26 Jun 2020, 15:10

Generally a good list but here are some things I noticed after reading it once :)

7: What do you want to enumerate in the case of file?
8: the issue isn't g it's gui. There is no local variable named gui.
13: How would you output that data?
Recommends AHK Studio
swagfag
Posts: 3981
Joined: 11 Jan 2017, 17:59

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

26 Jun 2020, 20:45

1. parser rewrites = ahk v3. probably
2, 3. i guess, more introspection is better
4. consequence of how strtol works, returns 0(black) if the conversion/parsing fails. making it throw would required extra parsing logic. or alternatively if gui option strings were to be removed(ie u set everything with properties exclusively .BackColor), u could make it accept integers and strings only. strtol wont be needed, neither would extra parsing
5. i guess
6. its hardcoded in source that prototype object cant be passed to for loops(throw automatically). what exactly do u expect a XXX.Prototype's enumerator to enumerate anyway?
7. such as?
8. no, it wants u to explicitly import the super-global Gui in the forced-local function scope
9. sounds very niche with all these additional stipulations, but i guess
10. more reasons to delete the command syntax. heres another one

Code: Select all

MsgBox('Text', 'Title')
MsgBox ('Nothing', 'Text')
11. check the docs changes, check the source changes, check the alpha updates thread, check v2-changes(which should be tracked somewhere btw hint hint)
12. no comment
13. i guess
14. indifferent
15. no comment
lexikos
Posts: 7068
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

27 Jun 2020, 21:34

vvhitevvizard wrote: I guess some of these optimizations r due to ...
More likely, the compiler has opaquely changed its optimization decisions. The changes to &var and On/Off should have zero effect on parts of the script that didn't use them in the first place.
for k,v in dbg2.prototype ;error: Type Mismatch
Map's __Enum method enumerates key-value pairs. It requires a Map. You gave it a Prototype, so __Enum threw a type mismatch exception. If you don't know what it is that you're enumerating, you should not be enumerating. If you want properties, use the OwnProps enumerator.
File and some other built-in objects should expose more properties for an enumeration.
All properties of all objects (except COM objects) are enumerable, but you must use OwnProps on the object that actually defines those properties. In future there might be an enumerator which builds a list of all inherited properties and enumerates those. In any case, there's no difference between enumerating properties of built-in objects vs. properties of user-defined objects.
msgbox("text"), abort ;???. it ignores the right side of the line
It isn't ignored; it just has no effect, like in x := (abort, 1). There's no "UseUnset" warning because the variable abort is not being used. This may be "fixed" when I change how unset variables are detected. (It is by design that some references do not cause a warning, such as for IsSet(abort).)
swagfag wrote:10. more reasons to delete the command syntax.
MsgBox(), abort not being detected as an error has nothing to do with function call statements. It simply is not an error. In this case I think vvhitevvizard was not trying to use a function call statement, and the existence of that feature did not inhibit error detection.
vvhitevvizard wrote:11. for k in obj acts different in v2-100 and v2-108. the former returns an index, the latter returns a key.
What kind of object is obj? In both versions, k depends on this. In v2-a100, in most cases it was a key (not index). In v2-a108, it is generally a key or array element.
v2.0-a104-3e7a969d
Major changes to the way objects and classes work.
See the documentation and v2-changes, and Objects.ahk for background information.
Source: AutoHotkey v2 alpha (UPDATES) - Page 3 - AutoHotkey Community
v2-changes wrote:Since array elements, properties and methods are now separate, enumerating properties and methods requires explicitly creating an enumerator by calling OwnMethods or OwnProps.
...
For-loop usage [for Array] is for val in arr or for idx, val in arr, where idx = A_Index by default. That is, elements lacking a value are still enumerated, and the index is not returned if only one variable is passed.
There is more detail in the documentation, under the __Enum method for whichever type of object you are enumerating.
vvhitevvizard wrote:There is no mention of removed .Count() for objects as well.
Under Map (in v2-changes) there is "Count is now a property." There is also "ObjCount was replaced with ObjOwnPropCount (a function only, for all Objects) and Map has its own Count property." ObjOwnPropCount(myMap) and myMap.Count and myArray.Length are counting different things.
varsetstrcapacity: 4 words within 1 keyword, why so long? Why not SetStrCapacity, StrCapacity or something?
1. Each word has meaning - it makes the purpose of the function clearer. It operates on a variable, not a string, but sets its capacity to hold strings.
2. It purposely discourages you from using the function. If you use it, you should feel the weight of its long name.
Four words... three of them are only three letters each, and you think that's long. :roll: What about UrlDownloadToFile or WinMenuSelectItem? FileCreateShortcut is fewer words but still longer.
15a. ControlGetList article is absent now:
That's because it is being renamed to ControlGetItems in the next update.
swagfag wrote:6. its hardcoded in source that prototype object cant be passed to for loops(throw automatically).
That's news to me. :roll:

Prototype objects cannot be passed (as this) to native methods belonging to specialized types, because Prototype objects are just a collection of properties and methods (natively just an Object). Taking a step back from the implementation, Map.Prototype is not an instance of Map; it has not been constructed, so calling instance methods on it is not valid.

However, any object or value can be passed to for if it has an __Enum or Call method that can be called. It doesn't need to have one by default - you can define one.
User avatar
vvhitevvizard
Posts: 405
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

28 Jun 2020, 03:54

I've just updated the first post - changes start from paragraph 13, added more bugs and suggestions, and merged my 2 previous topics. So to have all the stuff in one place. :D
Helgef
Posts: 4459
Joined: 17 Jul 2016, 01:02
Contact:

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

28 Jun 2020, 04:21

minimal setup to re-produce the error:
This is probably closer to the minimum,

Code: Select all

f
f()=>f()
Cheers.
User avatar
vvhitevvizard
Posts: 405
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

28 Jun 2020, 04:31

@Helgef yeah. :) What I want is catching such stuff that might be left by an user by an oversight. :)
Helgef
Posts: 4459
Joined: 17 Jul 2016, 01:02
Contact:

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

28 Jun 2020, 04:50

I don't feel that recursive calls should be prohibited.
User avatar
vvhitevvizard
Posts: 405
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

28 Jun 2020, 04:56

@Helgef Maybe its better to introduce some new #warn mode then? Check for # of recursions. E.g. 256 nested calls -> throw a warning. Or the opposite, a switch allowing it. With error signalling by default.
And my example is a tad different - we call outer function inside nested function/closure. And both have the same name... there might be a check at loading time to warn about this.

@nnnik
7: What do you want to enumerate in the case of file?
Self-logging script. File.pos, etc. One could just do a general for-in loop thru classes/global vars to save the current script's state. File object might be not the best example. But exposing as many properties as possible is not a bad thing for built-in objects.
8: the issue isn't g it's gui. There is no local variable named gui.
but gui.new should act as array.new. gui should be a super-global class name, right?
13: How would you output that data?
I added an example in the 1st post. Pls have a look.

--------------------

@swagfag

Code: Select all

1. parser rewrites = ahk v3. probably
We r in an eternal alpha state, there is no backward compatibility reasoning! :) And I thought "expression is too long" issue leads to some constant limiting it artificially.
3... or alternatively if gui option strings were to be removed(ie u set everything with properties exclusively .BackColor), u could make it accept integers and strings only. strtol wont be needed, neither would extra parsing
this! instead of going thru combining/parsing string of arguments like this: "s16 Bold Center vcenter c" var1 " "x " var2 " y15"
we could exploit gui/gui control class features adding
gc:=guictrl.new(), gc.style:="Bold", gc.align:="center",gc.valign:="center", gc.color:=var1, gc.x:=var2
Further away from AHK1ish quirks and closer to uniformity.
6. what exactly do u expect a XXX.Prototype's enumerator to enumerate anyway?
I was trying to enumerate my objects to store current script's state as JSON output to a file. And It throws when I tried to enumerate some of my objects due to them extending Map class.
If u r curious, here is the code:
Spoiler
so its used like json.dump(obj_name) to have pretty-printed/compressed output of an object. its good to debug objects ad hoc as well
8. no, it wants u to explicitly import the super-global Gui in the forced-local function scope
Oh, I see now! Anyways, I used to pre-face a function body with listing of all the locals - just a habit and it helps tracing which 1-letter names r not taken yet (I prefer local vars to be tersely named): :D

Code: Select all

local a,c,d,f, i,j, k,l,m,  p,q,z
g:=gui.new()
9. sounds very niche with all these additional stipulations, but i guess
Consider it as basic elements to speed up routine cycles. Ok, drop aside trimming (its up to a programmer to feed dirty input, it can be filtered with regex). But the core conversion has to be as fast as possible. Adding just a KB to the .exe by implementing map.fromstr(), map.tostr() or something, we boost performance for such [niche] functionality. of course this logic can be done via AHK script loop. But good performing list/tuple/range/dictionary/other is one of the key features that made Python so popular as a scripting language, I guess. And AHKv2 possesses greater possibilities as well, being a state of art scripting language.
10. more reasons to delete the command syntax.
yuppers! And there r not so many commands left to be converted :D

Code: Select all

11... check the alpha updates thread, check v2-changes(which should be tracked somewhere btw hint hint)
yeah I follow those files and even keep my own version of all the update notes, those v2-changes, lexikos' posts combined, and with added heavy highlighting to keep track what keywords got removed/renamed
Clipboard01.png
Clipboard01.png (67.71 KiB) Viewed 4735 times
Updating scripts to new alpha versions is not a big deal if all the changes r mentioned. :)
13. i guess
I added an example of such an extended command usage, and added more points and some details to old ones. please have a look at 1st post.
User avatar
vvhitevvizard
Posts: 405
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

28 Jun 2020, 08:45

@lexikos
The changes to &var and On/Off should have zero effect on parts of the script that didn't use them in the first place.
No checks for & preceding next keyword in the main cycle? :D
6... It requires a Map. You gave it a Prototype, so __Enum threw a type mismatch exception. If you don't know what it is that you're enumerating, you should not be enumerating.
The point is I just used a general recursive cycling thru all the exposed properties/nested objects of an object derived from Map. And I started from the surface.

Code: Select all

for k,v in (_o.hasmethod("__Enum") ? _o:_o.ownprops())
Function logic here is if something of built-in matter has __Enum then it can be enumerated via regular for k,v in obj and it should expose something w/o throwing. Otherwise we fall back to browsing thru obj's properties via for k,v in obj.ownprops().
Pls look at the full code in the post above this to get an idea why would one need to get there. :)
10... It isn't ignored; it just has no effect, like in x := (abort, 1).
I see. Well, all that stems from mixing command syntax with function syntax... Until we eradicate commands one day.
11... There is more detail in the documentation [skip]
Thank u for providing links... It renders point 11 as irrelevant.
Last edited by vvhitevvizard on 28 Jun 2020, 10:56, edited 3 times in total.
Helgef
Posts: 4459
Joined: 17 Jul 2016, 01:02
Contact:

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

28 Jun 2020, 09:01

my example is a tad different - we call outer function inside nested function/closure.
That is not what actually happens though.
User avatar
vvhitevvizard
Posts: 405
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

28 Jun 2020, 09:37

@Helgef
That is not what actually happens though.
Execution routine after gc.onevent goes to F1() (nested function) and then we call ourselves, not an outer one. u r right :thumbup: I updated 1st post.
But the point is the stuff silently crashes breaking even thru the scripts's critical error terminating route, not reaching catch/onerror/onexit control points. I would like to have a #warn setting mode to do some sanity check at loading time for presence of recursive calls to warn. In case a programmer let it be by mistake. Just in case. Recursion is a type of programming art not just anyone can master w/o dramatic performance drop and thus it rarely used in actual practice.
Or any changes to the interpreter to make it able to intercept at runtime long _before_ it crashed, devoured the whole memory and dealt other ruining.
If a script can ruin an interpreter w/o explicitly fiddling with process of the latter via system calls/external tools then its the interpreter fault after all.
Last edited by vvhitevvizard on 28 Jun 2020, 11:57, edited 2 times in total.
User avatar
vvhitevvizard
Posts: 405
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

28 Jun 2020, 10:56

@lexikos
It purposely discourages you from using the function. If you use it, you should feel the weight of its long name.
:D I knew u would mention it! Its use is very rare now indeed - mostly I see only 1 usage case of setting capacity big enuf to accommodate many strings concatenations w/o resorting to malloc().
14... Each word has meaning - it makes the purpose of the function clearer.
But common sense of AHK Creator should insist on making keywords as short as possible. Some long-tail keywords r too cumbersome to be easy-to-handle. Don't u ever reflected on having an "online" command line interface an interpreter should have? To type script's code line by line and immediately see the reaction. Great for small formulas.
If u wend this route of "every sub-word in a keyword is meaningful" then nothing would stop u from creating more and more prefixes and suffixes to keywords as time passes by...
StrCapacity() is the compromise IMHO - it has a return value so Set suffix is kinda confusing here. And we tackle a string variable, not a numeric one - so Var is redundant. IMHO. Its 11 letters still to be quite discouraging! :D

Pls check it I updated the 1st post adding more reasoning from an AHK user point of view. Up to point 23 now.
lexikos
Posts: 7068
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

28 Jun 2020, 16:56

15. I will probably leave BufferAlloc as is or replace it with Buffer.Alloc(). I originally named it BufferAlloc and not BufferCreate or BufferNew because I anticipated other ways to construct a Buffer object. And when it comes to low level stuff like this, I think the added clarity is important.

I disagree with the suggestion to use File.New(). FileOpen opens a file for reading or writing, and returns an object that can be used to read or write. It does not make a new file. I'll probably rename the class to something like FileHandle, FileIO, FileStream, IOStream, etc. Internally there's a C++ class named TextStream that does most of the work, but we're not always dealing with text.
... and it should expose something w/o throwing.
What do you think a Prototype is for? 1) It is not intended to be used directly, except to define things for instances. 2) It cannot define methods for itself, because all methods are intended for instances of the class. Your approach is incorrect; you must give special handling to Prototype objects (or avoid touching them), regardless of whether they actually throw an exception.
But the point is the stuff silently crashes breaking even thru the scripts's critical error terminating route, not reaching catch/onerror/onexit control points.
If the program has run out of stack space, it is unable to handle any script-level exceptions or execute script, and must terminate. It's up to the OS and system settings whether you get an error message; generally the error is logged (see Event Viewer, Application log). See Show error or debug dialog on Call Stack overflow - Suggestions.
The point is I just used a general recursive cycling thru all the exposed properties/nested objects of an object derived from Map.
You don't know the meaning of the values returned by __Enum by some arbitrary object, but it's likely that they aren't properties. I've used the convention that __Enum returns a key or index corresponding to __Item, but other objects can do whatever they want. If you want your script to be fault-tolerant while using unknown methods, you need to use exception handling. And in general, don't call anything on a Prototype.
No checks for & preceding next keyword in the main cycle?
The expression is parsed when the script is loaded, not during "the main cycle".
But common sense of AHK Creator should insist on making keywords as short as possible.
This is your opinion, and I obviously disagree.
And we tackle a string variable, not a numeric one - so Var is redundant.
That makes no sense. "Var" is to distinguish between variables and values, not strings and numbers. StrPtr works with string values. VarSetStrCapacity works only with variables. The variable does not have to contain a string before you call it, but it will after.
Well, all that stems from mixing command syntax with function syntax...
I already explained that it does not. Or is it because you were attempting to use a function call statement? If so, that's your choice. But given that you "accidentally inserted a command from NSIS", I assume you weren't actually cognizant of what is valid in AutoHotkey anyway, so whether or not we support function call statements is irrelevant.
lexikos
Posts: 7068
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

28 Jun 2020, 17:18

BufferFrom(Ptr, Size) ... would be very dangerous
It would be no more dangerous at worst, and safer at best, than the alternative - using Ptr directly, without the bound checking granted by Size. It's not about reusing memory, but accessing data from some source that does not create a Buffer (probably a DllCall). If you are the one allocating the memory, you can just use BufferAlloc and reuse the Buffer.
Would it be possible to have a default for .member syntax
No. That's reserved for line continuation.


I think your "documentation issues" #3 and #5 were fixed before you posted about them.
User avatar
vvhitevvizard
Posts: 405
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

29 Jun 2020, 03:03

lexikos wrote:
28 Jun 2020, 17:18
I think your "documentation issues" #3 and #5 were fixed before you posted about them.
Great :D I noted above I just merged my 2 old topics into this one. Just to to have my thoughts "centralized". Previous were 2+ months old.
Now I start hiding resolved/irrelevant points under spoilers.

BTW, what do u think of point 12? In general it needs some vars declaration ability within an expression of fat-arrow. To be able to inline local vars usage. Right now I cannot use local variables inside fat-arrow function that declared at global scope. And all that mess is due to fat-arrows at outer scope r assume-global...

21... No. That's reserved for line continuation.
Currently, its vacant for new syntax rules: concatenation/line continuation requires spaces between . operator:

Code: Select all

msgbox("aa"."bb") ;error
msgbox("aa" ."bb") ;error
msgbox("aa". "bb") ;error

a:="aa"
	."bb" ;error
msgbox(a)

a:="aa", b:="bb"
msgbox(b .a) ;error.  what about this one to have another meaning inside methods -> msgbox(b this.a) ?

a:="aa", b:="bb"
c:=a
	.b ;error. and same for here
msgbox(c)
-> Error: Illegal character in expression

15... I disagree with the suggestion to use File.New(). FileOpen opens a file for reading or writing, and returns an object that can be used to read or write. It does not make a new file.
But it does create an AHK built-in object for further operations via its methods. Even tho we create a new file handle just for reading w/o creating anything new at file system level: new relates here to creating a new AHK object.
17... If you are the one allocating the memory, you can just use BufferAlloc and reuse the Buffer.
Let's imagine,we've got a huge memory region created not by AHK's bufferalloc/File.RawRead or others. It might be an aftereffect of some external library call. We do have a pointer and we know a current size of that region and we want to use Buffer object facilities to control its boundaries and to tackle it using NumPut or other Buffer-aware functions. And we don't wanna waste CPU and memory resources by copying that memory region.
b:=BufferFrom(addr, size) and voila! We've just reduced our carbon dioxide emission level! :D
6... Your approach is incorrect; you must give special handling to Prototype objects (or avoid touching them), regardless of whether they actually throw an exception.
But additional checkup or additional try/catch block would slowdown the inner loop. And the whole function loop might be very resource-intensive, I remind u - some of my output JSON files r 10+MB in size. Is it possible to just remove __Enum property for items that r not supposed to be for-in looped?
You don't know the meaning of the values returned by __Enum by some arbitrary object, but it's likely that they aren't properties. I've used the convention that __Enum returns a key or index corresponding to __Item, but other objects can do whatever they want. If you want your script to be fault-tolerant while using unknown methods, you need to use exception handling. And in general, don't call anything on a Prototype.
Actually for the function logic it doesn't matter what data type for-in loop returns. It handles any valid AHK entity (numeric/string var, object, empty /zero length ones) w/o any errors. The exception happens inside for k,v in obj.
16... If the program has run out of stack space, it is unable to handle any script-level exceptions or execute script, and must terminate. It's up to the OS and system settings whether you get an error message
Thank u for sharing that link. But I meant an inability for a script that ran autonomously for a period of time to terminate itself in a regular way to save some critical data etc. And there is no way to control RSP (stack pointer) inside AHK scripts... It might be possible to implement some checkups inside CPP code. Im not sure how to do that for ur VisualCPP build but for GCC it goes like this:

Code: Select all

register void *sp asm ("sp");
printf("%p", sp);
Anyways, what do u think of having a warning about presence of any recursive calling enabled by default and requirement of using some #warn mode disabling syntax to let it be in the script? For the reason its potentially dangerous. And most time any recursive calling is left unintentionally by function misnaming.
Last edited by vvhitevvizard on 29 Jun 2020, 11:35, edited 4 times in total.
User avatar
vvhitevvizard
Posts: 405
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

29 Jun 2020, 05:41

@lexikos
It would be no more dangerous at worst, and safer at best, than the alternative - using Ptr directly, without the bound checking granted by Size.
:D Its dangerous in that sense it creates the false impression of safety having boundary checking while using a random memory region.
The expression is parsed when the script is loaded, not during "the main cycle".
:thumbup: Roger that!
This is your opinion, and I obviously disagree.
I just suggest. Sometimes plainly brainstorming. Naming is not of top-importance, but some of my points are, I guess. Especially one concerning refactoring of preprocessor - google "ahk preprocessor" - it might be one of the most desired features to add.
Your task is to weigh suggestions and decide whatever balanced changes to be done. So far so good - U've done great job - AHK v2 feels state-of-the-art. But its never-ending progress.
"Var" is to distinguish between variables and values, not strings and numbers. StrPtr works with string values. VarSetStrCapacity works only with variables. The variable does not have to contain a string before you call it, but it will after.
ok. StrPtr is from a binary formats family and VarSetStrCapacity belongs to a variables family.
I just don't like longtail keywords... BTW what do u think of having "String class" overloading with "".len() to exist in the language by default? ;)
Or is it because you were attempting to use a function call statement? If so, that's your choice. But given that you "accidentally inserted a command from NSIS", I assume you weren't actually cognizant of what is valid in AutoHotkey anyway, so whether or not we support function call statements is irrelevant.
From a user point of view: indignation here b/c of I inserted a random literal name after closing function's arguments list parenthesis and AHK ignored it.
I guess AHK logic here its a concatenation of msgbox("here") return value and undeclared var's value that is equal to "".
It might be on purpose for some cases but leftovers that r usually plain typos left by a script programmer r going unhandled.
Its expected to throw some warning for non-declared var usage in an expression/function call w/o any function definition somewhere else. As it happens regularly in recent AHK v2 versions.
Also, the result of the expression that has no assignment, not used as a parameter for a function call, and is not used by return, should have a respective #warn mode...
And overall I hate all that command syntax. I avoid uing any commands except for plain loop/else/break/throw. 8-)
lexikos
Posts: 7068
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

29 Jun 2020, 22:47

If I used a random memory region, I would not have an impression of safety, false or otherwise.
I guess AHK logic here its a concatenation
You guess wrong. If you removed the comma, it would be concatenation. With the comma, it's a multi-statement expression.

If you insert random text into a script file, there is a non-zero chance that it will be misinterpreted as something legitimate. That is not a problem of the language or the program; it is your problem.

As for referencing an uninitialized variable in this context, it will raise a warning by default in the next release, even though its value is not being used.

There will be no warning for merely lacking a declaration (because an undeclared variable can be assigned a value). Variable declarations are intentionally optional.

Language - Expression Statements wrote:Expressions that start with any of those described above (but not those described below) are also allowed, for simplicity. For example, MyFunc()+1 is currently allowed, although the +1 has no effect and its result is discarded. Such expressions might become invalid in the future due to enhanced error-checking.

And overall I hate all that command syntax.
You are free to hate and blame, but it changes nothing. Again, command syntax has nothing to do with MsgBox(), somevar.
lexikos
Posts: 7068
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

29 Jun 2020, 23:08

Right now concatenation/line continuation requires spaces between dot operator so place for new syntax is not taken yet
Stop editing replies into your first post.

Anyway, you are mistaken yet again. a ."b" is obviously invalid, because valid identifiers cannot contain quote marks. a .b is obviously invalid if a has no b property. Strings have no b property by default.

Code: Select all

a := {b: 42}
c := a
  .b
MsgBox c
12. Fat arrow functions are intended for passing to other functions inline, and generally will be referring to variables from the outer scope. If you need to create local variables, use a proper function, or define the fat arrow function inside another function. How many functions must you define in global scope, that you need to cram them onto one line?

23. You can do whatever you want by overloading the __Item property.
But it does create an AHK built-in object for further operations via its methods.
So do FileRead (with the RAW parameter) and other functions, for other types of objects. Maybe there will be other functions that return an IO object.
Let's imagine
I live in the real world (for some of the time), and can't recall ever encountering a need for what you describe, in AutoHotkey.
But additional checkup or additional try/catch block would slowdown the inner loop.
But incorrect code will make your program not work. Is it better to fail quickly?
Is it possible to just remove __Enum property for items that r not supposed to be for-in looped?
I think you're missing the point of a Prototype. If you remove a method from the Prototype, objects derived from it will no longer have that method...
But I meant
I have no idea what you're talking about.
Anyways, what do u think of having a warning about presence of any recursive calling enabled by default
Like Helgef said, no.

v1.1.33 and v2.0-a113 will catch the stack overflow exception and display a message. By that point, the entire call stack will have unwound, so there will be no chance of recovery.
User avatar
vvhitevvizard
Posts: 405
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Updated from v2-108 to v2-112. Just a bliss! Feels so good. But a [list of bugs/suggestions]

30 Jun 2020, 03:43

lexikos wrote:
29 Jun 2020, 22:47
As for referencing an uninitialized variable in this context, it will raise a warning by default in the next release, even though its value is not being used.
:thumbup:
There will be no warning for merely lacking a declaration (because an undeclared variable can be assigned a value). Variable declarations are intentionally optional.
Assignment w/o declaration is ok for a scripting language of loosely typed simplified system, right side operand (string, integer, float, object) defines its type. But using a value of non-declared and non-assigned variable should be an error!
10... You guess wrong. If you removed the comma...
Oh dang I forgot about the comma. I'm cursory here and there. I hope people to not split hairs, I pleaded for the issue of garbage text used w.o any errors to be addressed.
Again, command syntax has nothing to do with...
Many issues of user's misunderstanding stem from AHK having 2 co-existing syntax systems of commands and functions.
e.g. https://www.autohotkey.com/boards/viewtopic.php?p=187731#p187731
lexikos wrote:
29 Jun 2020, 23:08
Stop editing replies into your first post.
That's the idea - to remove some wrong conclusions of mine and distracting stuff and add details to outline the essence of the wish list.
And I'm desperate - some stuff I tried to bump up seems to be very daunting for the AHK developers team so despite of multiple [similar issue] requests year by year it seems to be never released.
Last edited by vvhitevvizard on 30 Jun 2020, 08:56, edited 2 times in total.

Return to “AutoHotkey v2 Development”

Who is online

Users browsing this forum: Bing [Bot] and 3 guests