AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting (https://forums.alliedmods.net/forumdisplay.php?f=107)
-   -   New API and Syntax (https://forums.alliedmods.net/showthread.php?t=244092)

BAILOPAN 07-13-2014 15:36

New API and Syntax
 
Hi, everyone! SourceMod 1.7 development is underway, and I'm excited to announce that SourcePawn is undergoing radical changes. The API is becoming object-oriented, and the syntax is becoming more C#/Java-like. All of the changes are opt-in, and old scripts will continue to compile.

Without further ado...

Motivation

Pawn is derived from "Small C", which was made in 1984. It has a number of severe syntactic and semantic flaws compared to modern languages, and it's become quite painful to use. All of its problems can be ultimately blamed on the tag system. The tag system erases type information, which prevents us from implementing garbage collection, which prevents us from implementing better datastructures, true arrays, true strings, objects, and lambda functions.

Our ultimate goal is for Pawn to become a "C# Lite", but getting there is difficult: we have to rewrite the compiler, the JIT, and our entire API. That's an insane amount of work, so we're taking a new approach by introducing transitional syntax, transitional APIs, and a transitional type system.

Hopefully we're killing two birds with one stone: we'll make a major dent in the tag system, put foundations in place for our future API, and provide some major short-term improvements to Pawn usability.

Syntax Changes
As of SourcePawn 1.7, there is a new preferred way of declaring variables and function signatures. Fans of Java/C# will find it much more familiar. Here are some before and after examples:

PHP Code:

// Before:
stock bool:IsUserACrab(client);

// After:
stock bool IsUserACrab(int client);

// Before:
public OnReceivedString(const String:name[], Float:fval);

// After:
public void OnReceivedString(const char[] namefloat fval);

// Before:
new Handle:PlayerHandles[MAXPLAYERS 1];

// After:
Handle PlayerHandles[MAXPLAYERS 1]; 

New-style declarations allow array dimensions to come either before or after the variable name. Empty dimensions should come before, and fixed-lengths should come after.

The new style is important for a few reasons. First, it visually removes the concept of tags. Second, it formalizes int as an actual type, replacing "cells" (which were part of the tag system). Third, it formalizes void, which will make it easier to implement modules in the future. Finally, it gives us a chance to replace old type names with better ones. For example, String is not only misnamed, but will be confusing when we have a true string type.

The new type names are int, float, char, void, and object, and are only available in new-style declarations. They cannot be used as tags.

Methodmaps

SourcePawn 1.7 has a new feature called "methodmaps" for creating object-oriented APIs. Most users will not be creating their own methodmaps, so I defer to the full documentation for the gory details. The idea is that you can now attach functions to tags.

For example:

PHP Code:

enum Player:
{
    
SERVER_PLAYER 0,
}

methodmap Player
{
    public 
void Kick(const char[] message) {
        
KickClent(this.Index"%s"message);
    }
    
property int Health {
        public 
get() {
            return 
GetClientHealth(this.Index);
        }
    }
    
property int Index {
        public 
get() {
            return 
int(this);
        }
    }


This methodmap lets us do things like:
PHP Code:

void CheckPlayerHealth(Player player)
{
    if (
player.Health 5)
        
player.Kick("Wow, you are very bad at this game.");



Object-Oriented API

We've ported adt_trie, adt_array, and menus. For example, creating a simple menu beforehand might have looked something like this:

PHP Code:

new Handle:menu CreateMenu(Menu_Handler)
AddMenuItem(menu"de_dust""Dust")
AddMenuItem(menu"cs_assault""Assault")
AddMenuItem(menu"cs_thunder""Thunder")
SetMenuExitButton(menutrue)
DisplayMenu(menuclient)
...
CloseHandle(menu); 

Now, you can write it like this:
PHP Code:

Menu menu Menu(MenuHandler)
menu.AddItem("de_dust""Dust")
menu.AddItem("cs_assault""Assault")
menu.AddItem("cs_thunder""Thunder")
menu.ExitButton true
menu
.Display(client)
...
delete menu 

Future Work

Most of our API has not yet been transitioned to methodmaps. I am hoping we'll be able to release 1.7 with a full object-oriented API, so if you want to use something in the includes that has not yet been ported, feel free to submit a patch!

We may also consider an automatic porting tool for plugins once enough of the API is available.

The full documentation for the transitional syntax is here: https://wiki.alliedmods.net/SourcePa...itional_Syntax

Please let me know if you have any questions.

Zephyrus 07-13-2014 15:52

Re: New API and Syntax
 
why, just why? at least before it was a language that was used by some other stuff like samp, but now this just makes it a new language to learn for a lot of ppl. javascript would be a better choice overall, as its the most widespread scripting language with the fastest JITs out there. also countless libraries have been written in js already...

VoiDeD 07-13-2014 15:57

Re: New API and Syntax
 
For developers looking to harness the methodmap syntax for an object-oriented API for interacting with game entities, check out these helpers includes.

Example of usage:
PHP Code:

stock void GiveObjectHatCBaseObject objectEnt, const char hatModelPLATFORM_MAX_PATH ] )
{
    
CBaseEntity hatProp Entity_CreateByName"prop_dynamic_override" );

    if ( 
hatProp.IsValid )
    {
        
hatProp.SetModelhatModel );
        
hatProp.Spawn();

        
hatProp.AcceptInput"DisableCollision" );
        
hatProp.AcceptInput"DisableShadow" );

        
ParentHathatPropobjectEnt );
    }
}

stock void ParentHatCBaseEntity hatPropCBaseObject objectEnt )
{
    
char hatModelPLATFORM_MAX_PATH ];
    
hatProp.GetModelhatModelsizeofhatModel ) );

    
float modelScale 1.0;
    
float modelOffset 0.0;

    if ( !
Config_GetHatByModelhatModelmodelOffsetmodelScale ) )
    {
        
LogError"Unable to find hat config for hat: %s"hatModel );
        return;
    }

    
hatProp.Skin objectEnt.Builder.Team 2;
    
hatProp.ModelScale modelScale;

    
char attachmentName128 ];
    
GetAttachmentNameobjectEntattachmentNamesizeofattachmentName ) );

    
hatProp.SetParentobjectEnt );
    
hatProp.SetParentAttachmentattachmentName );

    
float vecPos]; float angRot];
    
hatProp.GetLocalOriginvecPos );
    
hatProp.GetLocalAnglesangRot );

    
// apply z offset
    
vecPos] += modelOffset;

    
// apply position/angle fixes based on object type
    
OffsetAttachmentPositionobjectEntvecPosangRot );

    
hatProp.TeleportvecPosangRotNULL_VECTOR );



Dr. Greg House 07-13-2014 16:10

Re: New API and Syntax
 
If I may keep it short.
<---------------------------

psychonic 07-13-2014 16:17

Re: New API and Syntax
 
Quote:

Originally Posted by BAILOPAN (Post 2167095)
All of the changes are opt-in, and old scripts will continue to compile.

I feel that this should be echoed.

Dr. Greg House 07-13-2014 16:34

Re: New API and Syntax
 
Quote:

Originally Posted by psychonic (Post 2167112)
I feel that this should be echoed.

I think this needs color, bigger font, and a big arrow.

Arkarr 07-13-2014 16:40

Re: New API and Syntax
 
Totally not okay with that :
Code:

// Before:
public OnReceivedString(const String:name[], Float:fval);

// After:
public void OnReceivedString(const char[] name, float fval);

Why 'char' instend of String ?

Zephyrus 07-13-2014 16:41

Re: New API and Syntax
 
Quote:

Originally Posted by Arkarr (Post 2167124)
Totally not okay with that :
Code:

// Before:
public OnReceivedString(const String:name[], Float:fval);

// After:
public void OnReceivedString(const char[] name, float fval);

Why 'char' instend of String ?

because if its a string you shouldnt need to use [] in the first place

Dr. Greg House 07-13-2014 16:42

Re: New API and Syntax
 
Quote:

Originally Posted by Arkarr (Post 2167124)
Totally not okay with that[...]

Because it is actually a char-array and not a string-array.

Arkarr 07-13-2014 16:45

Re: New API and Syntax
 
Nevermind, thanks.

BAILOPAN 07-13-2014 16:46

Re: New API and Syntax
 
Quote:

Originally Posted by Arkarr (Post 2167124)
Why 'char' instend of String ?

The reason is alluded to in the post, but it's worth clarifying. In normal type systems, the concept of a "string" is a data type in and of itself. For example:

PHP Code:

string x "hello!"

In Pawn, it is:
PHP Code:

String:x[] = "hello1"

Here, "String" is really a storage modifier affecting how the array is allocated. It's not actually a string - it's just telling the array that it's an array of characters. It looks like a string, but it's a hack. Long-term we want to provide a true string type. It's important that we begin to eliminate the concept of String: ahead of time, to eliminate any confusion. char may be unfamiliar but it's much more true to what's actually going on.

I myself look forward to a point in time when we have API calls like this:
PHP Code:

native string GetClientName(int client); 


pheadxdll 07-13-2014 17:03

Re: New API and Syntax
 
1. Can you separate a class's code from it's declaration? I see all the code in the methodmap declaration.
2. Is SM 1.7 stable enough to run on a live server? :3

Arkarr 07-13-2014 17:22

Re: New API and Syntax
 
@BAILOPAN
If I have understand correctly, this is wrong :
PHP Code:

public bool PrintMessageToAll(string message)
{
     
PrintToChatAll(message);
     
PrintToConsole(message);
     return 
true;


and this is correct ?
PHP Code:

public bool PrintMessageToAll(const char[] message)
{
     
PrintToChatAll(message); //But PrintToChatAll() only accept 'pawn string' so char should work as well without formating value ?
     
PrintToConsole(message); //same as PPrintToChatAll() ?
     
return true;



VoiDeD 07-13-2014 17:25

Re: New API and Syntax
 
Quote:

Originally Posted by pheadxdll (Post 2167138)
1. Can you separate a class's code from it's declaration? I see all the code in the methodmap declaration.

Not (yet?). See https://bugs.alliedmods.net/show_bug.cgi?id=6182 for something similar.

Quote:

Originally Posted by pheadxdll (Post 2167138)
2. Is SM 1.7 stable enough to run on a live server? :3

The majority of the changes thusfar are related to the compiler. The rest of SM should run just fine on a live server, at least in the current state. I assume there will be no such promises once JIT changes come into play.

Also, you should be able to run plugins compiled in 1.7 on a 1.6 server, again: at least for now.

Powerlord 07-13-2014 22:15

Re: New API and Syntax
 
So, basically this is replacing all the SourcePawn 2.0 stuff that was happening before?

BAILOPAN 07-13-2014 23:02

Re: New API and Syntax
 
Quote:

Originally Posted by pheadxdll (Post 2167138)
1. Can you separate a class's code from it's declaration? I see all the code in the methodmap declaration.
2. Is SM 1.7 stable enough to run on a live server? :3

1. No.
2. Right now 1.7 is basically the same as 1.6 with some compiler changes. So it should be stable. I'm hoping that 1.7 will be mostly an API refactoring release.

BAILOPAN 07-13-2014 23:03

Re: New API and Syntax
 
Quote:

Originally Posted by Powerlord (Post 2167251)
So, basically this is replacing all the SourcePawn 2.0 stuff that was happening before?

I don't want to commit to anything but there's a reason the API is called "Transitional".

GsiX 07-14-2014 07:43

Re: New API and Syntax
 
Look like i have to start all over again and catch up with the rest of the new beginner.

WildCard65 07-14-2014 08:32

Re: New API and Syntax
 
Quote:

Originally Posted by BAILOPAN (Post 2167095)
All of the changes are opt-in, and old scripts will continue to compile.

I highly doubt that old scripts can compile on SM 1.7 atm...
See: https://travis-ci.org/50DKP/FF2-Official
But other then that, taking a look at method maps documentation link, they are REALLY AWESOME! Much neater then current system as it actually makes things easier to understand.

Wliu 07-14-2014 10:40

Re: New API and Syntax
 
Quote:

Originally Posted by WildCard65 (Post 2167415)
I highly doubt that old scripts can compile on SM 1.7 atm...
See: https://travis-ci.org/50DKP/FF2-Official
But other then that, taking a look at method maps documentation link, they are REALLY AWESOME! Much neater then current system as it actually makes things easier to understand.

Do note that the current compiler errors are only with morecolors.inc...which is not included with SM.
It looks to me more like a compiler bug (looking at the line numbers and error #) than "1.6 is incompatible with 1.7".

VoiDeD 07-14-2014 10:43

Re: New API and Syntax
 
Quote:

Originally Posted by WildCard65 (Post 2167415)
I highly doubt that old scripts can compile on SM 1.7 atm...
See: https://travis-ci.org/50DKP/FF2-Official
But other then that, taking a look at method maps documentation link, they are REALLY AWESOME! Much neater then current system as it actually makes things easier to understand.

Try to reduce your problem to the simplest test case and file a bug.

TheWho 07-14-2014 18:58

Re: New API and Syntax
 
Again a milestone for every developer, nice!

LambdaLambda 07-14-2014 21:51

Re: New API and Syntax
 
Hate me, but I loved SP for it's syntax. :(

BAILOPAN 07-14-2014 23:00

Re: New API and Syntax
 
Quote:

Originally Posted by LambdaLambda (Post 2167792)
Hate me, but I loved SP for it's syntax. :(

I think you'll find the syntax much more fluid after using it for a bit. The lack of colons everywhere lowers code density. I do realize "new" had a very typeless feel to it that gets lost with "int". I think we'll be able to solve that eventually though.

Thrawn2 07-16-2014 12:32

Re: New API and Syntax
 
I've adapted the smjansson includes and test plugin to the new syntax to see how it feels. Here
This was quite easy and i'm really pleased with the new syntax. Good job!

Have one question though: How to deal with e.g. INVALID_HANDLE checks? Cast (i.e. tag) the methodmap as a Handle before comparison?

splewis 07-16-2014 13:25

Re: New API and Syntax
 
Looks awesome. Can't wait to give it a spin! :)

BAILOPAN 07-16-2014 13:57

Re: New API and Syntax
 
Quote:

Originally Posted by Thrawn2 (Post 2168755)
I've adapted the smjansson includes and test plugin to the new syntax to see how it feels. Here
This was quite easy and i'm really pleased with the new syntax. Good job!

Have one question though: How to deal with e.g. INVALID_HANDLE checks? Cast (i.e. tag) the methodmap as a Handle before comparison?

I forgot to mention it in the first post, but there's a new constant you can use, null, which is way easier to type. It should cast to any Handles or anything inheriting from Handle. INVALID_HANDLE should work too though if you still want to use it - if it doesn't, send me the code and I can take a look.

Thrawn2 07-17-2014 12:54

Re: New API and Syntax
 
Quote:

Originally Posted by BAILOPAN (Post 2168806)
I forgot to mention it in the first post, but there's a new constant you can use, null, which is way easier to type. It should cast to any Handles or anything inheriting from Handle. INVALID_HANDLE should work too though if you still want to use it - if it doesn't, send me the code and I can take a look.

Neat.

Using INVALID_HANDLE does work if I cast the methodmap to a Handle first, null on the other hand does only work if i cast it to the corresponding object type.

E.g. this does not work unless the comparison is: f != StringMap:null
Code:

#include <sourcemod>

public OnPluginStart() {
        StringMap f = StringMap();

        LogMessage("StringMap is not null? %d", f != null);
}

Without the cast it results in:
sm17.test.sp(6) : error 132: cannot coerce non-object type StringMap to object type null_t

Is there a way to avoid tagging of null or the other value altogether?

Also more questions if you don't mind:
  • "any", while quite hacky was also quite useful. E.g. the old tests include used by smjansson had a method Tests_Is(any:a, any:b) which compared a to b. This worked with int, float, handle, i.e. you could throw anything at it. How would one specify an any: parameter in the new syntax?
  • Will there be the possibility to define multiple constructors with a different set of parameters?
  • When exactly is the destructor being called? When I delete the object and before the "old" CloseHandle is being performed?

And one bug report: it is possible to crash the compiler by using delete instead of CloseHandle.
It is easily reproducible by changing line 1013 of the previously linked smjansson include to use delete and trying to compile the test plugin that comes with it. Sorry for not having a smaller and more specific testcase for this.

Thanks!

Edit: The wiki says:
Quote:

Currently only "get" accessors are available.
Is this accurate? The menus include is using property setters.

BAILOPAN 07-18-2014 00:53

Re: New API and Syntax
 
Quote:

Originally Posted by Thrawn2 (Post 2169353)
E.g. this does not work unless the comparison is: f != StringMap:null

Good catch! This has been fixed on master.

Quote:

Originally Posted by Thrawn2 (Post 2169353)
"any", while quite hacky was also quite useful. E.g. the old tests include used by smjansson had a method Tests_Is(any:a, any:b) which compared a to b. This worked with int, float, handle, i.e. you could throw anything at it. How would one specify an any: parameter in the new syntax?

The reason any is not available in the new syntax is fairly technical... the way it interacts with natives makes it impossible to do run-time type checking. It's verboten in the transitional syntax. On the other hand - it currently sees a lot of use and the replacements I have in mind (generics or top-type object) are nowhere near ready. I'll add any back on master for all but new-style natives.

Quote:

Originally Posted by Thrawn2 (Post 2169353)
Will there be the possibility to define multiple constructors with a different set of parameters?

Overloading - yes! Eventually, I hope.

Quote:

Originally Posted by Thrawn2 (Post 2169353)
When exactly is the destructor being called? When I delete the object and before the "old" CloseHandle is being performed?

delete is syntactic sugar for immediately invoking the destructor. That is, delete handle is equivalent to handle.~CloseHandle() (if that were valid syntax).

Quote:

Originally Posted by Thrawn2 (Post 2169353)
Edit: The wiki says:
Is this accurate? The menus include is using property setters.

I've updated the wiki to reflect that setters are available.

ddhoward 07-18-2014 01:37

Re: New API and Syntax
 
Quote:

All of the changes are opt-in, and old scripts will continue to compile.
Do you imagine this changing in the future? Once the 'transition' is complete, will these old scripts still function?

BAILOPAN 07-18-2014 01:38

Re: New API and Syntax
 
Quote:

Originally Posted by Thrawn2 (Post 2169353)
And one bug report: it is possible to crash the compiler by using delete instead of CloseHandle.
It is easily reproducible by changing line 1013 of the previously linked smjansson include to use delete and trying to compile the test plugin that comes with it. Sorry for not having a smaller and more specific testcase for this.

Thanks for such an excellent test of the new syntax! I extracted a minimal test case from your file and now it's fixed on master.

BAILOPAN 07-18-2014 01:59

Re: New API and Syntax
 
Quote:

Originally Posted by ddhoward (Post 2169679)
Do you imagine this changing in the future? Once the 'transition' is complete, will these old scripts still function?

I don't think we could get away with breaking old scripts. What we can do though is build really awesome new tools, and only allow transitioned code in the new tools. I don't know if we'll get there, but if we do - we'll be shipping two compilers and two VMs in SourceMod.

xf117 07-18-2014 03:55

Re: New API and Syntax
 
Thank you! i've been waiting for something like this for a long time.
Please, don't stop even if it means breaking compatibility with old scripts.

sheo 07-19-2014 13:10

Re: New API and Syntax
 
Disliked this topic. For objects and classes we have C++

KissLick 07-19-2014 13:27

Re: New API and Syntax
 
But sometimes working with objects & classes is much easier...

Thrawn2 07-19-2014 16:31

Re: New API and Syntax
 
Nice, thanks for the fixes.

Found another bug regarding null passed as an any parameter though:
Code:

Foo(any foo) {}
public Bar() {
Foo(null);
}

Edit:
A rather cosmetic issue: combining getters and setters works if used like this
this.Processed = this.Processed + 1;
which is nice.
this.Processed++ garbles up the value though.

This is at least the case for methodmaps deriving from StringMap and setting an integer in the trie, i.e.
Code:

methodmap Foo < StringMap {
  property int Bar {
    public get() {
      int result;
      this.GetValue("foo.bar", result);
      return result;
    }
    public set(int value) {
      this.SetValue("foo.bar", value);
    }
  }
}


BAILOPAN 07-19-2014 17:46

Re: New API and Syntax
 
Sorry, fat-fingered and garbled your post up a bit. re: increment bug, will take a look soon.

null not flowing into any is intended. any makes the bit-encoding of values observable which is illegal for object types, and null is considered an object type. While not strictly necessary in this case, it makes sure we don't have any GC-safety problems with null in the future.

Thrawn2 07-20-2014 00:47

Re: New API and Syntax
 
Quote:

Originally Posted by BAILOPAN (Post 2170562)
null not flowing into any is intended.

I see. It crashes the compiler though.

BAILOPAN 07-21-2014 01:25

Re: New API and Syntax
 
Quote:

Originally Posted by Thrawn2 (Post 2170678)
I see. It crashes the compiler though.

Ah! Okay, that's fixed on master. The postinc/postdec bug is fixed as well. Turns out my initial implementation was just clownshoes. I made sure to test it better this time.

Bubka3 07-21-2014 02:35

Re: New API and Syntax
 
So I read over this about 5 times. Maybe I'm stupid (I probably am) but I just don't see the need for this. The reason I got in coding 4 years ago, is because of the simplicity of the SourcePawn language and the need to make my server more unique. I remember not knowing what anything means (my worst enemy was tag mismatch), but still getting basic things done like printing to chat, setting health, etc. After awhile, I finally began to really learn why I was getting tag mismatch, why this was done, why that was done. With C#/Java or "C# Lite" as it's been called in the first post I still probably would have been unable to exactly understand why most things are done are that way. Sure I could probably make some basic edits (because words and I can read), but I wouldn't be able to get the true meaning of things as I did for SourcePawn. I think the current ease of language not only allows complete newbies to try, but it also opens doors. It certainly did for me.

Quote:

Originally Posted by BAILOPAN (Post 2167095)
Pawn is derived from "Small C", which was made in 1984. It has a number of severe syntactic and semantic flaws compared to modern languages, and it's become quite painful to use. All of its problems can be ultimately blamed on the tag system. The tag system erases type information, which prevents us from implementing garbage collection, which prevents us from implementing better datastructures, true arrays, true strings, objects, and lambda functions.

On the other hand, that (what I underlined) and the fact that I started with SourcePawn would probably explain why I am having a real hard time getting into newer modern languages, especially when they are object-based.


All times are GMT -4. The time now is 07:30.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.