 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Pil
Joined: 26 Feb 2006 Posts: 55 Location: Recife Brazil
|
Posted: Sun Nov 23, 2008 2:39 pm Post subject: |
|
|
| What about writing code that permits use of ASM code in script using __mcode(FuncName, Hex). Not that I donīt like C, but most of languages I saw use Asm to speed up things. I am reading the GoAsm manual, seems to suit perfectly. |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4367 Location: Qld, Australia
|
Posted: Sun Nov 23, 2008 9:42 pm Post subject: |
|
|
| ASM can be used as the source language for __mcode just as easily as C. Either way the code must be compiled/assembled first. |
|
| Back to top |
|
 |
Pil
Joined: 26 Feb 2006 Posts: 55 Location: Recife Brazil
|
Posted: Sun Nov 23, 2008 10:47 pm Post subject: |
|
|
Thatīs what I meant.
Writing code that reads permitted asm line code in source script, then makes an .obj file with GoAsm, links it with GoLink,disassambles the exe with disassem, and takes machinecode out of produced txt file to put it in as an __mcode function on compile time.
Or another way? |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4367 Location: Qld, Australia
|
Posted: Mon Nov 24, 2008 7:58 am Post subject: |
|
|
Since "mcode" is short for "machine code," the function you describe would have to be __asm.
I've never even heard of GoAsm before you mentioned it. You seem to have a reasonable understanding of how it might work, so why not try it yourself?
It is also feasible to write a basic assembler in AutoHotkey, using the Intel documentation as reference.
(If anyone has wondered what I've been working on the last few weekends...) |
|
| Back to top |
|
 |
Pil
Joined: 26 Feb 2006 Posts: 55 Location: Recife Brazil
|
Posted: Mon Nov 24, 2008 10:36 pm Post subject: |
|
|
BITMAP example by SKAN with __mcode funcion by Lexikos.
| Code: | ATC:=A_TickCount
SetBatchLines -1
DetectHiddenWindows, On
#include lowlevel.ahk
; Creating a 256x256 24bit bitmap file in memory
Id:="BM",Hdr:=54,W:=256,H:=256,Bit:=24,Byt:=W*H*(Bit/8), VarSetCapacity(BMP,Hdr+Byt,0)
NumPut( NumGet( Id,0,"UShort" ),BMP,0,"UShort" ), NumPut( Hdr+Byt,BMP,2 )
NumPut( Hdr,BMP,10 ), NumPut( 40,BMP,14 ), NumPut( W,BMP,18 ), NumPut( H,BMP,22 )
NumPut( 1,BMP,26,"UShort" ), NumPut( Bit,BMP,28,"UShort" ), NumPut( Byt,BMP,34 )
Gui, 99:+AlwaysOnTop +ToolWindow +LastFound
Gui99:=WinExist(), hDC:=DllCall("GetDC",UInt,Gui99)
Gui, 99:Add, Text, w256 h256 0x120E hWndhPic gSelColor
;LowLevel.ahk required.
prepare_bitmap(bmp){
}LowLevel_init(),__mcode("prepare_bitmap"
, "8B4424088B088B118B0283C03633D29033C988104088084"
. "0C60000414081F9000100007CED4281FA000100007CE2C3")
prepare_bitmap(BMP)
hBMP := DllCall( "CreateDIBitmap", UInt,hDC, UInt,&BMP+14, Int,4, UInt,&BMP+NumGet(BMP,10)
, UInt,&BMP+14, UInt,1 )
SendMessage, (STM_SETIMAGE:=0x172), (IMAGE_BITMAP:=0x0), hBMP,, ahk_id %hPic%
Gui, 99:Show,, % "ColorPicker [ " (A_TickCount-ATC) "ms ]"
Return
SelColor:
MouseGetPos, X, Y
PixelGetColor,Color, X, Y, RGB
Tooltip % SubStr(Color,-5)
SetTimer, TooltipOff, -2000
Return
ToolTipOff:
ToolTip
Return
GuiClose:
ExitApp |
Lightning fast... giving me the enthousiam trying to write an "automation script" making possible to write simple asm code in AHK script.
However:
| Lexikos wrote wrote: | It is also feasible to write a basic assembler in AutoHotkey, using the Intel documentation as reference.
(If anyone has wondered what I've been working on the last few weekends...) |
Are you saying that thatīs where you are working on?
PS. Above script gives an error using beta version. |
|
| Back to top |
|
 |
tinku99
Joined: 03 Aug 2007 Posts: 308 Location: Houston, TX
|
Posted: Sun Dec 07, 2008 11:00 am Post subject: save function created by __expr |
|
|
I am able to keep the temp function created by __expr
as follows:
| Code: | __expr(expr, pScopeFunc=0, function = "__expr_sub")
{
static pThisFunc
pFunc:=__getFuncUDF(function), pThisFunc:=__getFuncUDF(A_ThisFunc), __init()
nInst := NumGet(pThisFunc+40)
VarSetCapacity(Line%nInst%,44,0), __static(Line%nInst%), pLine:=&Line%nInst%
if ! __ParseExpressionArg(expr, pArg:=&Line%nInst%+32, pScopeFunc)
return
NumPut(pArg,NumPut(1,NumPut(102,pLine+0,0,"char"),0,"char"),2)
, NumPut(pLine,NumPut(pLine,pLine+16))
, NumPut(pLine,pFunc+4)
, ret := %function%()
return ret
}
|
However, all the functions i create seem to point to the last function created.
| Code: | setq(ByRef var, val){
var = %val%
}
myMsg(msg)
{
Msgbox % msg
}
function1() {
global
; Contents replaced at run-time by __expr.
}
function2() {
global
; Contents replaced at run-time by __expr.
}
F11:: ;; test various dynamic functions
setq(x, 5)
setq(y, 7)
__expr("myMsg(y)", 0, "function2")
__expr("myMsg(x)", 0, "function1")
function1()
function2()
return
|
|
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4367 Location: Qld, Australia
|
Posted: Sun Dec 07, 2008 12:01 pm Post subject: |
|
|
| Pil wrote: | | Are you saying that thatīs where you are working on? | Yes. You give the script basic assembly source, and it spits out a hexadecimal string. It is at a "functional but not useful" state. When it gets far enough to at least implement the simple function I wrote for SKAN's example, I'll start a thread. (Please save any further discussion until then.)
| Quote: | | PS. Above script gives an error using beta version. | I likely won't write a fix until after the next official (non-beta) release of AutoHotkey.
| tinku99 wrote: | | I am able to keep the temp function created by __expr as follows: | __expr reuses the same structures for each call, except when a previous call is still running. Below is an alternative which replaces the function's body, but does not call it. It should not be used on a given function more than once as it does not free the memory used by the text and derefs.
| Code: | x=Ex.
y=Why?
LowLevel_init()
__expr_("function2", "myMsg(y)")
__expr_("function1", "myMsg(x)")
function1()
function2()
__expr_(function, expr, pScopeFunc=0)
{
__init()
pFunc:=__getFuncUDF(function)
VarSetCapacity(Line%function%,44,0), __static(Line%function%), pLine:=&Line%function%
if ! __ParseExpressionArg(expr, pArg:=&Line%function%+32, pScopeFunc)
return false
NumPut(pArg,NumPut(1,NumPut(102,pLine+0,0,"char"),0,"char"),2)
, NumPut(pLine,NumPut(pLine,pLine+16))
, NumPut(pLine,pFunc+4)
return true
}
myMsg(msg)
{
Msgbox % msg
}
function1() {
global
; Contents replaced at run-time by __expr.
}
function2() {
global
; Contents replaced at run-time by __expr.
} |
If you have a practical use for this, would you mind posting a demonstration? |
|
| Back to top |
|
 |
tinku99
Joined: 03 Aug 2007 Posts: 308 Location: Houston, TX
|
Posted: Tue Dec 09, 2008 8:40 pm Post subject: dynamic function creation |
|
|
| Lexikos wrote: |
If you have a practical use for this, would you mind posting a demonstration? |
Thanks Lexikos. That works.
I was just playing around with it.
No specific use for it yet. |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4367 Location: Qld, Australia
|
Posted: Mon Jan 05, 2009 10:01 am Post subject: |
|
|
I recently realised that __expr cannot easily be made to work with the pre-v1.0.48 beta, since all expressions must be pre-tokenized before evaluation. In other words, it would need to implement a full expression parser, which is simply something I will not do. (If Line::ExpressionToPostfix() were exposed to script it would be possible, but permanent memory would be allocated for each expression evaluated.)
This makes easier my decision to stop development on LowLevel indefinitely, instead focusing my efforts on AutoHotkey_L. I intend to eventually introduce similar functionality.
That aside, some of you may find the following script interesting, especially those that know what the uses of an anonymous function are (since my example is not useful):
| Code: | private=no
FuncA()
FuncA()
{
static _T,_F ; Generate the exression function only once.
if !_T
LowLevel_init(),_T:=__findFunc(A_ThisFunc)
private=yep
; Demonstrate that FuncB cannot access 'private' directly.
MsgBox % FuncB("private")
; Demonstrate that via _T, functions created by __function CAN access our local variables.
MsgBox % FuncB(__function(_F,"private '!'",_T) "()")
}
FuncB(x)
{
if SubStr(x,-1)="()"
{
F := SubStr(x,1,-2)
return %F%()
}
else
return (%x%)
}
; Builds a function from a given expression, and returns its name.
; DO NOT CALL if func_buf has been assigned contents or given
; non-zero capacity by anything other than this function.
; IT IS NOT SAFE to simply clear func_buf since it will not release
; resources allocated by __ParseExpressionArg.
__function(ByRef func_buf, expr="", pScopeFunc=0)
{
static ACT_RETURN:=102, VAR_ASSUME_LOCAL:=1
, SIZE_FUNC:=52, SIZE_LINE:=32, SIZE_ARGSTRUCT:=12
, func_index:=0
LowLevel_init()
if !(first_func:=__getFirstFunc())
return ; FATAL ERROR.
; Recommended usage is to use 'func' to conveniently cache the result.
; func MUST have capacity=0 unless set by a previous call to this function.
if VarSetCapacity(func_buf)
return __str(NumGet(func_buf))
if expr =
return ; OOPS!
; Function name can be anything since AutoHotkey won't be validating it.
func_index += 1
VarSetCapacity(func_buf, SIZE_FUNC + SIZE_LINE + SIZE_ARGSTRUCT + StrLen(func_index) + 1, 0)
ptr_func := &func_buf
ptr_line := ptr_func + SIZE_FUNC
ptr_arg := ptr_line + SIZE_LINE
ptr_name := ptr_arg + SIZE_ARGSTRUCT
DllCall("lstrcpy","uint",ptr_name,"str",func_index) ; Copy name into buffer.
NumPut(ptr_name, ptr_func + 0) ; Func->Name
NumPut(ptr_line, ptr_func + 4) ; Func->JumpToLine
NumPut(VAR_ASSUME_LOCAL, ptr_func + 48, 0, "char") ; Func->DefaultVarType
NumPut(ACT_RETURN | 1<<8, ptr_line + 0, 0, "short") ; Line->{ActionType,Argc}
NumPut(ptr_arg, ptr_line + 4) ; Line->Arg
; ArgStruct will be initialised by the following call:
__ParseExpressionArg(expr, ptr_arg, pScopeFunc)
; Now that Func, Line and ArgStruct are valid, insert function into list.
NumPut(NumGet(first_func + 44), ptr_func + 44)
NumPut(ptr_func, first_func + 44)
return func_index ; Name, not address.
}
| It has similar functionality to __expr_ in my previous post, but creates an entirely new function rather than overwriting an existing one.
A more useful function would support something like:
| Code: | MyFunc(myparam) {
...
Foreach(list, __function(_F
, "(f, i) => mylocal .= f + myparam * i . ','"
,_T))
}
Foreach(list, func, delim=",") {
Loop, Parse, list, %delim%
%func%(A_LoopField, A_Index)
} | Entirely untested and probably useless pseudo-code. Yes, it is entirely feasible. |
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 4975 Location: /b/
|
Posted: Mon Jan 05, 2009 12:10 pm Post subject: |
|
|
| Lexikos wrote: | | (f, i) => mylocal .= f + myparam * i . ', | I see what you're doing there. While syntax sugar like delegates and reflection can be useful to fluent programmers, the typical AutoHotkey user would probably never get the hang of them. You could end up with feature bloat as py3k has taught us, not to mention the massive waste of time for the developer. Keep us updated on your new ideas though, it'll help me decide what to work into the IA lexer when I do it the first time round - like arrays for example. _________________
 |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4367 Location: Qld, Australia
|
Posted: Tue Jan 06, 2009 8:20 am Post subject: |
|
|
| Titan wrote: | | You could end up with feature bloat as py3k has taught us, | It's a hypothetical script, not a proposal for a built-in feature.
| Quote: | | not to mention the massive waste of time for the developer. | Given its dependence on __expr, it would be only a small waste of time. Not small enough, I think.
| Quote: | | While syntax sugar like delegates and reflection can be useful to fluent programmers, | What I was suggesting was merely an extension of the function to allow a list of parameter names without requiring an extra parameter. As it is, the generated function cannot have parameters.
What does reflection have to do with syntax sugar?
| Quote: | | the typical AutoHotkey user | ...has nothing to do with this thread.  |
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 4975 Location: /b/
|
Posted: Tue Jan 06, 2009 11:04 am Post subject: |
|
|
| Lexikos wrote: | | It's a hypothetical script, not a proposal for a built-in feature. | My statement was a hypothetical response.
| Lexikos wrote: | | some of you may find the following script interesting, especially those that know what the uses of an anonymous function are |
| Lexikos wrote: | | an extension of the function to allow a list of parameter names without requiring an extra parameter. | In some languages there are anonymous delegates and object initializers. What you're describing is a mix of both, can you be more clear?
| Lexikos wrote: | | What does reflection have to do with syntax sugar? | In the low level (pun intended) sense that here it would cause a conversion to an intermediate form, or "pre-tokenized before evaluation [Line::ExpressionToPostfix()]." Anyway the point is not to discuss the definition of syntax sugar, I don't want to hijack this thread with another debate over semantics.
| Lexikos wrote: | | Quote: | | the typical AutoHotkey user | ...has nothing to do with this thread. | I probably haven't understood who the target audience for your AutoHotkey fork exactly is. Going by your response I would assume the proficient few programmers, correct? _________________
 |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4367 Location: Qld, Australia
|
Posted: Tue Jan 06, 2009 12:40 pm Post subject: |
|
|
| Titan wrote: | | In some languages there are anonymous delegates and object initializers. What you're describing is a mix of both, can you be more clear? | I was a bit vague, speaking only in the context of __function.
__function creates a "Func" structure which can be dynamically called by AutoHotkey to evaluate an expression and return its result. My "idea" was strictly limited to allowing __function to add parameters to the "Func" it creates, for use in the expression.
| Quote: | | In the low level (pun intended) sense that here it would cause a conversion to an intermediate form, or "pre-tokenized before evaluation [Line::ExpressionToPostfix()]." | Thanks for the explanation. I now see what reflection has to do with the script, but my original point remains: Syntax defines how a functionality is accessed, but is not itself functional.
The way I see it now, dynamic function calls provide the capability for delegation, and LowLevel provides the capability for reflection. Neither are syntax, but the former is represented by such: %func%(). This you could say is syntax sugar, as there are longer ways to achieve similar results without having syntax specifically for it.
This brings me to __function("(params)=>expression") - syntax sugar for __function("params","expression"). (Just one way of placing less importance on the "params" param.)
| Quote: | | I don't want to hijack this thread with another debate over semantics. | By debating semantics, I come to a better understanding of what you really mean, rather than what I would mean if I spoke those words.
While the script I posted uses "reflection" to allow a function to be defined in-line, if it were a built-in feature as in C#, "reflection" would not be necessary. From a user's perspective, they are not using reflection, but using functionality made feasible by it.
| Quote: | | I probably haven't understood who the target audience for your AutoHotkey fork exactly is. | What I meant was that this thread, LowLevel, is absolutely not intended for typical AutoHotkey users - i.e. those that "would probably never get the hang of" its functionality. |
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 4975 Location: /b/
|
Posted: Tue Jan 06, 2009 3:46 pm Post subject: |
|
|
It was misleading of me to suggest that dynamic code or reflection is syntax sugar, with the same logic one could argue looping is no different as it can be done with conditional gotos. What I meant to refer to was the added stages in the lexer such that if "(params)=>expression" were to be converted to "params","expression" then reparsed and evaluated no new functionality has been added as far as the parser is concerned, hence low level syntactic sugar.
| Lexikos wrote: | | By debating semantics, I come to a better understanding of what you really mean, rather than what I would mean if I spoke those words. | As I see it there can only be a single definition. I am not a professional programmer so if my understanding is incorrect please let me know.
| Lexicos wrote: | | What I meant was that this thread, LowLevel, is absolutely not intended for typical AutoHotkey users |
| Lexicos earlier wrote: | | This makes easier my decision to stop development on LowLevel indefinitely, instead focusing my efforts on AutoHotkey_L. | My posts were in fact directed towards your AutoHotkey fork and the concepts you're taking over from this script. Here seemed like the right place to discuss it. _________________
 |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4367 Location: Qld, Australia
|
Posted: Tue Jan 06, 2009 9:59 pm Post subject: |
|
|
| Quote: | | My posts were in fact directed towards your AutoHotkey fork and the concepts you're taking over from this script. Here seemed like the right place to discuss it. | I should have qualified "similar functionality" by saying I intend to implement only a few key functionalities, like "reflection" and __expr. |
|
| 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
|