AutoHotkey Community

It is currently May 26th, 2012, 9:28 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 173 posts ]  Go to page Previous  1 ... 6, 7, 8, 9, 10, 11, 12  Next
Author Message
 Post subject: dynamic code
PostPosted: July 20th, 2009, 6:11 am 
Offline

Joined: August 3rd, 2007, 8:01 am
Posts: 555
Location: Houston, TX
HotkeyIt, Have you tried the "import" function in AutoHotkey_N?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 20th, 2009, 5:43 pm 
Offline

Joined: June 18th, 2008, 8:36 am
Posts: 4923
Location: AHK Forum
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 :o

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.


:oops: 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

_________________
AHK_H (2alpha) AHF TT _Struct WatchDir Yaml _Input ObjTree RapidHotkey DynaRun :wink:


Report this post
Top
 Profile  
Reply with quote  
PostPosted: August 1st, 2009, 10:04 pm 
Offline

Joined: August 3rd, 2007, 8:01 am
Posts: 555
Location: Houston, TX
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 August 16th, 2009, 12:53 am, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 4th, 2009, 5:26 pm 
Offline

Joined: April 22nd, 2009, 6:04 am
Posts: 29
please, tinku99
do you have documentation of the built-in lowlevel functions of AutoHotkey_N? :)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 4th, 2009, 9:59 pm 
Offline

Joined: August 3rd, 2007, 8:01 am
Posts: 555
Location: Houston, TX
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 15th, 2009, 2:20 am 
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


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: August 15th, 2009, 3:08 am 
er ... sorry bad example ...

var1 := "var2 > var3"
if (__expr(var1))
{
some stuff
}


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: August 15th, 2009, 5:37 am 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7502
Location: Australia
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 27th, 2009, 2:38 pm 
Offline

Joined: June 26th, 2006, 6:14 pm
Posts: 1379
Location: USA
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

_________________
Image
ʞɔпɟ əɥʇ ʇɐɥʍ


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 27th, 2009, 3:15 pm 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7502
Location: Australia
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 27th, 2009, 3:39 pm 
Offline

Joined: June 26th, 2006, 6:14 pm
Posts: 1379
Location: USA
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??

_________________
Image
ʞɔпɟ əɥʇ ʇɐɥʍ


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 27th, 2009, 4:15 pm 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7502
Location: Australia
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.
Quote:
we can access it
No.
Quote:
Maybe a better alternative ...
Yes, but that's off-topic.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 27th, 2009, 9:51 pm 
Offline

Joined: June 26th, 2006, 6:14 pm
Posts: 1379
Location: USA
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

_________________
Image
ʞɔпɟ əɥʇ ʇɐɥʍ


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 28th, 2009, 2:54 am 
Offline

Joined: June 26th, 2006, 6:14 pm
Posts: 1379
Location: USA
help


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 28th, 2009, 4:07 am 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7502
Location: Australia
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.
Quote:
help
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.


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 173 posts ]  Go to page Previous  1 ... 6, 7, 8, 9, 10, 11, 12  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: MSN [Bot] and 15 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group