 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
tinku99
Joined: 03 Aug 2007 Posts: 309 Location: Houston, TX
|
Posted: Mon Jul 20, 2009 6:11 am Post subject: dynamic code |
|
|
| HotkeyIt, Have you tried the "import" function in AutoHotkey_N? |
|
| Back to top |
|
 |
HotKeyIt
Joined: 18 Jun 2008 Posts: 2173 Location: GERMANY
|
Posted: Mon Jul 20, 2009 5:43 pm Post subject: |
|
|
| Lexikos wrote: | | No. adviseUDF inserts a line containing a function call into an existing function. __curry creates a new function containing a function call. They do not run the code. |
Damn, I have to study them
| Lexikos wrote: | | Anything related to dynamic expressions will not work, so code_arg(cg, 0, true) and any subsequent code_arg_* calls. |
I hope it will be available in the future, that feature is really superb.
| Lexikos wrote: | | I have already gone over it more than once. |
Sorry to be a pain, I will try to understand __Call(), __curry() and adviseUDF() and will get back if I face any problems, OK
Thanks tinku99, I have tried AutoHotkey_N.exe it but Import() does not return a pointer but a character?
| Code: | line_ptr:=Import("x:\test1.ahk")
MsgBox % line_ptr |
_________________ AutoHotFile - ToolTip(n,text,title,options) |
|
| Back to top |
|
 |
tinku99
Joined: 03 Aug 2007 Posts: 309 Location: Houston, TX
|
Posted: Sat Aug 01, 2009 10:04 pm Post subject: Re: LowLevel-AutoHotkey_L (in)compatibility etc. |
|
|
| Lexikos wrote: | tinku99 recently pointed out that LowLevel is not currently compatible with AutoHotkey_L...
Func::mNextFunc has been removed in favour of the binary-searchable array Script::mFunc. This breaks __getFirstFunc, but disabling __getFirstFunc does not help in this instance. (__findFunc is able to work a more direct approach for __getVar etc. as they have no ByRef or optional parameters.) |
So, if we just expose the builtin FindFunc, maybe LowLevel can be more easily adapted for your AutoHotkey48_L30.
| Code: | EXPORT unsigned int ahkFindFunc(char *funcname)
{
return (unsigned int)g_script.FindFunc(funcname);
}
void BIF_FindFunc(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount)
{
aResultToken.symbol = SYM_INTEGER ;
aResultToken.marker = "";
char funcname_buf[MAX_NUMBER_SIZE];
char *funcname = TokenToString(*aParam[0], funcname_buf);
int funcname_length = (int)EXPR_TOKEN_LENGTH(aParam[0], funcname);
aResultToken.value_int64 = (__int64)ahkFindFunc(funcname);
return;
}
|
Are you sure you don't want to keep AutoHotkey_L compatible with LowLevel? [/code]
Last edited by tinku99 on Sun Aug 16, 2009 12:53 am; edited 1 time in total |
|
| Back to top |
|
 |
wiseley
Joined: 22 Apr 2009 Posts: 21
|
Posted: Tue Aug 04, 2009 5:26 pm Post subject: |
|
|
please, tinku99
do you have documentation of the built-in lowlevel functions of AutoHotkey_N?  |
|
| Back to top |
|
 |
tinku99
Joined: 03 Aug 2007 Posts: 309 Location: Houston, TX
|
Posted: Tue Aug 04, 2009 9:59 pm Post subject: |
|
|
| wiseley wrote: | please, tinku99
do you have documentation of the built-in lowlevel functions of AutoHotkey_N?  |
The builtin lowlevel functions are:
| Code: | FindFunc
Getvar
Static
Alias
CacheEnable
GetTokenValue
|
i just removed the underscores from their names, otherwise they should work as the original LowLevel.ahk functions.
I will try to create a nice html help file some day. |
|
| Back to top |
|
 |
TheGMan Guest
|
Posted: Sat Aug 15, 2009 2:20 am Post subject: |
|
|
So I have been using AHK (1.0.47) and Low Level for the expr functionality. I see that expr no longer works with 1.0.48. The way I use expr is storing an expression in a variable and using expr to evaluate in an if statement ... like this ...
var1 := "var2 > var3"
if (__expr(%var1%))
{
some stuff
}
Its a long story as to why I do things this way, but was wondering if there is another solution I could use with 1.0.48 to obtain the performance improvements.
Thanks in advance
G |
|
| Back to top |
|
 |
TheGman Guest
|
Posted: Sat Aug 15, 2009 3:08 am Post subject: |
|
|
er ... sorry bad example ...
var1 := "var2 > var3"
if (__expr(var1))
{
some stuff
} |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4468 Location: Qld, Australia
|
Posted: Sat Aug 15, 2009 5:37 am Post subject: |
|
|
| TheGMan wrote: | | was wondering if there is another solution I could use with 1.0.48 to obtain the performance improvements. | I'm not aware of any. |
|
| Back to top |
|
 |
ahklerner
Joined: 26 Jun 2006 Posts: 1317 Location: USA
|
Posted: Thu Aug 27, 2009 2:38 pm Post subject: |
|
|
how to get the name of the current OnExit Routine ? can be done with this low-level lib?
hey i figured it out ! (kind of cludgy)
| Code: | GetCurrentOnExitRoutine(){
LowLevel_init()
ACT_ONEXIT = 97
line_ptr := __getFirstLine()
loop
{
ActionType := NumGet(line_ptr+0, 0, "UChar")
if (ActionType = ACT_ONEXIT)
{
pLabel := NumGet(line_ptr+12, 0, "UInt")
break ;
}
line_ptr := NumGet(line_ptr+20, 0, "UInt")
}
return __getTokenValue(pLabel+0)
}
|
here's why: to be able to call the users onexit routine when there is stuffs you have to make sure gets done for your lib, without bothering the user to code it. here is what i got:
| Code: | a := 1
a := 1
a := 1
a := 1
OnExit,UserExitRoutine
LIB_Init()
return
LIB_Init(){
global A_UserExitSub
A_UserExitSub := GetCurrentOnExitRoutine()
OnExit, LIBExitRoutine
; ...
}
LIBExitRoutine:
MsgBox YAY LIBExitRoutine!
;... your LIB exit stuffs
If IsLabel(A_UserExitSub) && A_UserExitSub != A_ThisLabel
GoSub, %A_UserExitSub%
ExitApp
esc::exitapp
UserExitRoutine:
MsgBox YAY UserExitRoutine!
ExitApp
GetCurrentOnExitRoutine(){
LowLevel_init()
ACT_ONEXIT = 97
line_ptr := __getFirstLine()
loop
{
ActionType := NumGet(line_ptr+0, 0, "UChar")
if (ActionType = ACT_ONEXIT)
{
pLabel := NumGet(line_ptr+12, 0, "UInt")
break ;
}
line_ptr := NumGet(line_ptr+20, 0, "UInt")
}
return __getTokenValue(pLabel+0)
}
#include LowLevel.ahk
|
_________________
ʞɔпɟ əɥʇ ʇɐɥʍ |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4468 Location: Qld, Australia
|
Posted: Thu Aug 27, 2009 3:15 pm Post subject: |
|
|
You've done well to figure that out. However, it will only work correctly if the first OnExit line in the script is the one which is in effect. If it is "OnExit" (used to remove the OnExit subroutine) or "OnExit %DynamicSub%" pLabel will be 0 and the result will be indeterminate; i.e. it'll probably crash.
| ahklerner wrote: | | return __getTokenValue(pLabel+0) | What makes you think pLabel points at an ExprTokenType structure? That it works is a fluke. Use this instead:
| Code: | return __str(NumGet(pLabel+0))
| There is no way to determine the active OnExit subroutine without using a wrapper function or the like. |
|
| Back to top |
|
 |
ahklerner
Joined: 26 Jun 2006 Posts: 1317 Location: USA
|
Posted: Thu Aug 27, 2009 3:39 pm Post subject: |
|
|
| Quote: | | What makes you think pLabel points at an ExprTokenType structure? | To be honest i wasn't really sure what to use, and _GetTokenValue sounded closer to what i wanted to do than _str.
the docs for _str read:
| Quote: | | Retrieves a string value from the given address. |
i took that to mean if you had a string in a var or something. since there was not more documentation, i assumed it maybe was just used inside your low level functions.
| Quote: | | There is no way to determine the active OnExit subroutine without using a wrapper function or the like. |
isnt there some fancy way to get a pointer to the current OnExit routine. i mean doesnt ahk internals keep that pointer somewhere we can access it with these functions or some numget(Your VooDoo Magic)?
Maybe a better alternative would be to wishlist having the OnExit command modified to update ErrorLevel with the previous OnExit routine?? _________________
ʞɔпɟ əɥʇ ʇɐɥʍ |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4468 Location: Qld, Australia
|
Posted: Thu Aug 27, 2009 4:15 pm Post subject: |
|
|
| ahklerner wrote: | | Quote: | | Retrieves a string value from the given address. |
i took that to mean if you had a string in a var or something. | An address is an address. If a string exists in memory, it has an address; i.e. a location. See "Pointers" -> "Pointer to a string" in LowLevel.chm.
| Quote: | | i assumed it maybe was just used inside your low level functions. | That's probably true. There are alternatives, such as calling strcpy directly, or this:
| Code: | ; s := __str(p)
s := DllCall("MulDiv", "int", p, "int", 1, "int", 1, "str")
|
| Quote: | | isnt there some fancy way to get a pointer to the current OnExit routine. | No.
| Quote: | | i mean doesnt ahk internals keep that pointer somewhere | Yes.
No.
| Quote: | | Maybe a better alternative ... | Yes, but that's off-topic. |
|
| Back to top |
|
 |
ahklerner
Joined: 26 Jun 2006 Posts: 1317 Location: USA
|
Posted: Thu Aug 27, 2009 9:51 pm Post subject: |
|
|
ok how to generate dynamic code to represent the following code?
| Code: |
SomeVar := "SomeText"
|
i tried this:
You can see the SomeVar := "SomeText" in lines most recently exectued, but not in listvars
| Code: | #a::
cg := code_gen()
ACT_ASSIGNEXPR = 2
code_line(cg, ACT_ASSIGNEXPR)
code_arg(cg)
code_arg_write(cg, "SomeVar")
code_arg_end(cg)
code_arg(cg)
code_arg_write(cg, """SomeText""")
code_arg_end(cg)
hcode := code_finalize(cg, 1)
code_run(hcode)
ListVars
|
edit: i also tried this to no avail
| Code: | #a::
cg := code_gen()
ACT_ASSIGN = 1
code_line(cg, ACT_ASSIGN)
code_arg(cg)
code_arg_write(cg, "SomeVar")
code_arg_end(cg)
code_arg(cg)
code_arg_write(cg, "SomeText")
code_arg_end(cg)
hcode := code_finalize(cg, 1)
code_run(hcode)
ListVars
|
_________________
ʞɔпɟ əɥʇ ʇɐɥʍ |
|
| Back to top |
|
 |
ahklerner
Joined: 26 Jun 2006 Posts: 1317 Location: USA
|
Posted: Fri Aug 28, 2009 2:54 am Post subject: |
|
|
| help |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4468 Location: Qld, Australia
|
Posted: Fri Aug 28, 2009 4:07 am Post subject: |
|
|
| code_arg wrote: | type
0: literal text or an expression.
1: an input variable.
2: an output variable.
...
For dynamic input/output vars, param should be zero. code_arg_write and code_arg_deref are used to write text or derefs into the arg.
For normal input/output vars, param must be a pointer to a Var. It is not valid to write text or derefs to the arg.
| A demonstration or three:
| Code: | LowLevel_init()
cg := code_gen()
ACT_ASSIGN = 1
ACT_ASSIGNEXPR = 2
ACT_LISTVARS := 205 + (A_AhkVersion>="1.0.48") ; ACT_WHILE puts these off by 1.
ACT_PAUSE := 193 + (A_AhkVersion>="1.0.48")
Loop 3
{
if A_Index<3
{
code_line(cg, ACT_ASSIGNEXPR)
code_arg(cg, 2, 0) ; 2: Output var. 0: Dynamic.
if A_Index=1
{
; Dynamic vars require at least one deref and at least one character
; of text. However, note that *deref* text is otherwise ignored.
; In this example, v cannot be used for more than one variable name
; since the code has a reference to v, not its contents.
code_arg_deref(cg, " ", __getVar(v:="SomeVar"))
}
else
{
; In this example, we get around the "at least one deref" rule by
; using a global empty variable, which can be used repeatedly.
; Each time the code is run, it will *dynamically* access "SomeVar".
code_arg_write(cg, "SomeOtherVar")
code_arg_deref(cg, "", __getVar(EmptyVar))
}
}
else
{
; Note that ACT_ASSIGNEXPR was used above even though we aren't really
; using an expression. If we use ACT_ASSIGN, AutoTrim affects the result:
code_line(cg, ACT_ASSIGN)
; In this example, we resolve the variable reference at run-time, but
; before the code is run. We could've done __getVar(SomeVar), but that
; would create a global variable at load-time; the first iteration (above)
; would then have accessed this global variable instead of creating a local.
v=SomeVar
code_arg(cg, 2, __getVar(%v%))
}
/* ; THE FOLLOWING REQUIRES v1.0.47.06 OR EARLIER:
code_arg(cg, 0, true) ; true: "Yes, it's an expression."
code_arg_write(cg, """SomeText""")
*/ ; OTHERWISE:
; This arg is not an expression. Expressions in string form aren't supported
; in AutoHotkey v1.0.48 or later, though tokenized expressions can be constructed.
code_arg(cg)
code_arg_write(cg, " SomeText ")
code_line(cg, ACT_LISTVARS)
code_line(cg, ACT_PAUSE)
if hcode := code_finalize(cg)
{
code_run(hcode)
code_delete(hcode)
}
}
code_gen_delete(cg)
|
Note that in the above, dynamic variables weren't really necessary. Instead, code_var can be used to create a variable to be inserted into the code. However, variables created this way cannot appear in the global variable list. Our dynamic code runs directly inside a function created by code_run; since this function is private to code_run we can't add the var to it's local variable list either.
For an interesting effect, add this to code_run:
| Code: | | __addVar(code_var("HELLO!"), &cb_func) | Notice that it bypasses normal variable naming rules:
- Any characters can be used.
- Any number of characters can be used, including zero or 1000.
- Any two or more variables can have the same name.
Variables with rule-breaking names may not be accessible by conventional means.
There was no need to bump; I was in the middle of writing this post. Also, there was no point: if I ignored you the first time, I'd more than likely ignore you the second time. |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|