Feature: Function/Pointer syntax
Opened this issue · 5 comments
In fact, it may not make sense to do so. But in theory, I hope that the sb tool can add more new OP writing methods. Essentially, I think we should add a new simple syntax to the frequently used basic OP and SA (CLEO4).VC.3 (CLEO2.0) OP
In fact, I got the idea from gosub:
gosub @xxxx
xxxx ()
But actually you should add highlighting to the above code
Back to the topic, I have an example:
0AA5: call 0x123456 num_params 3 pop 3 0@ 1@ 2@
Maybe this:
call 0x123456 (3 2@ 1@ 0@)
call 0x123456 3(2@ 1@ 0@)
By writing call address + (parameter), the SB tool can automatically detect the number of parameters (num_params) in () when compiling.
In fact (3 2@ 1@ 0@), the 3 in () should be the pop parameter. In fact, OP 0AA5 fills the parameters in CLEO upside down, which is very uncomfortable. 2@ should be the first parameter
More examples:
0AA5: call 0x123456 num_params 3 pop 3 0@ 1@ 2@
call 0x123456 (3 2@ 1@ 0@)
0AA6: call_method 0x123456 struct 30@ num_params 3 pop 3 0@ 1@ 2@
call 0x123456 30@(3 2@ 1@ 0@)
0AA7: call_function 0x123456 num_params 3 pop 3 0@ 1@ 2@ ret 3@
call 0x123456 (3 2@ 1@ 0@) ret 3@
0AA8: call_function_method 0x123456 struct 30@ num_params 3 pop 3 0@ 1@ 2@ ret 3@
call 0x123456 30@(3 2@ 1@ 0@) ret 3@
0AB1: call_scm_func @xxxx 3 0@ 1@ 2@ ret 3@ 4@ 5@
call xxxx (3 0@ 1@ 2@)ret 3@ 4@ 5@
:xxxx
0AB2: ret 3 3@ 4@ 5@
ret (3@ 4@ 5@)
ret 0 = ret
Just like the example, the sb tool automatically detects the number of parameters (). But the above code is still not good. Such as pop and struct parameters. Maybe it can be declared at the beginning:
var
this 30@
stdcall 0x654321
cdecl 0x123456
end
call 0x123456 (30@ 2@ 1@ 0@}
call 0x654321 (30@ 2@ 1@ 0@}
In the end I suggest this
call address + (parameter)
pop and struct can be declared at the beginning
Or like this
var
this 30@
end
0AA5: call 0x123456 num_params 3 pop 3 0@ 1@ 2@
0AA5: call 0x123456 num_params 3 pop 0 0@ 1@ 2@
_cdecl call 0x123456 (2@ 1@ 0@)
_stdcall call 0x123456 (2@ 1@ 0@)
0AA6: call_method 0x123456 struct 30@ num_params 3 pop 3 0@ 1@ 2@
0AA6: call_method 0x123456 struct 30@ num_params 3 pop 0 0@ 1@ 2@
_cdecl call 0x123456 (30@ 2@ 1@ 0@)
_stdcall call 0x123456 (30@ 2@ 1@ 0@)
0AA7: call_function 0x123456 num_params 3 pop 3 0@ 1@ 2@ ret 3@
0AA7: call_function 0x123456 num_params 3 pop 0 0@ 1@ 2@ ret 3@
_cdecl call 0x123456 (2@ 1@ 0@) 3@
_stdcall call 0x123456 (2@ 1@ 0@) 3@
0AA8: call_function_method 0x123456 struct 30@ num_params 3 pop 3 0@ 1@ 2@ ret 3@
0AA8: call_function_method 0x123456 struct 30@ num_params 3 pop 0 0@ 1@ 2@ ret 3@
_cdecl call 0x123456 (30@ 2@ 1@ 0@) 3@
_stdcall call 0x123456 (30@ 2@ 1@ 0@) 3@
0AB1: call_scm_func @xxxx 3 0@ 1@ 2@ ret 3@ 4@ 5@
_scm call xxxx (0@ 1@ 2@) 3@ 4@ 5@
:xxxx
0AB2: ret 3 3@ 4@ 5@
ret (3@ 4@ 5@)
@XMDS thanks for the feedback.
But actually you should add highlighting to the above code
IDE should highlight a callable label:
Does that work for you?
Regarding functions. Yes I want to expand on functions syntax more. Gosubs were just an easy change and I want to implement a similar syntax for SCM functions and call opcodes.
You don't have to specify calling convention (stdcall/cdecl) each time you call a function. Basically I would introduce a new syntax for functions declaration where you can tell the compiler how many arguments it takes and other information. Something like:
declare external function my_function at 0x123456 params 3 stdcall
then
my_function(0@,1@,2@) // 0AA5: call 0x123456 num_params 3 pop 0 2@ 1@ 0@
or
30@.my_function(0@,1@,2@) // 0AA6: call_method 0x123456 struct 30@ num_params 3 pop 0 2@ 1@ 0@
or
(3@,4@,5@) = my_function(0@,1@,2@) // 0AA7: call_function 0x123456 num_params 3 pop 0 2@ 1@ 0@ ret 3@ 4@ 5@
or
(3@,4@,5@) = 30@.my_function(0@,1@,2@) // 0AA8: call_function_method 0x123456 struct 30@ num_params 3 pop 0 2@ 1@ 0@ ret 3@ 4@ 5@
changing stdcall
to cdecl
would change the resulting pop value to 3
still not sure about multiple returning values syntax, but this is a draft.
@x87
Regarding the command to get the pointer, we have a discussion here:
#136
Should it be like the function syntax, instead of using the class form, but using the independent form, for example:
0AC7: 1@ = var 0@ pointer
1@ = 0@*
0AC6: 0@ = label @label pointer
0@ = @label*
0A9F: 0@ = get_this_script_struct
0@ = Script*
0AAA: 0@ = get_script_struct_named 'xxx'
0@ = Script* 'xxx'
Can be declared for people, cars, and obj pointers:
0A96: 0@ = ped $PLAYER_ACTOR struct
0A97: $CarStruct = vehicle $MyCar struct
0A98: $ObjectStruct = object 0@ struct
Var
0@ : char
1@ : Car
2@ : Object
3@s: Script
end
0@ = 0@*
1@ = 1@*
2@ = 2@*
3@ = 3@s* //3@ = Script* 'xxx'
Should also support const……end instruction to define pointer writing of variable names. The above are all my personal suggestions. If there is a better grammar, I can discuss it
*
can be confused with multiplication, hence it's ambiguous.
My proposal would be a syntax similar to Rust - adding &
in front of the variable returns its address. So:
0AC7: 1@ = var 0@ pointer
1@ = &0@
0AC6: 0@ = label @label pointer
0@ = &@label
this won't have collisions with ADMA syntax as ADMA variables are always numeric.
for entities:
0A96: 0@ = ped $PLAYER_ACTOR struct
0A97: $CarStruct = vehicle $MyCar struct
0A98: $ObjectStruct = object 0@ struct
Var
0@ : char
1@ : Car
2@ : Object
3@s: Script
end
0@ = &0@ // however it's not clear whether we want variable pointer or entity pointer, maybe needs a dereference operator like: 0@ = &*0@
1@ = &1@
2@ = &2@
not sure about syntax for the script pointer. maybe leave it as a keyword:
0@ = get_this_script_struct
0@ = get_script_struct_named 'xxx'
*
can be confused with multiplication, hence it's ambiguous.My proposal would be a syntax similar to Rust - adding
&
in front of the variable returns its address.
I very much agree, because I also thought of using * or &, indeed the latter is better