Raised This Month: $32 Target: $400
 8% 

SourceGo: Golang to SourcePawn Transpiler (v1.4 beta)


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
nergal
Veteran Member
Join Date: Apr 2012
Old 11-02-2020 , 17:18   SourceGo: Golang to SourcePawn Transpiler (v1.4 beta)
Reply With Quote #1

I'm happy to announce that, with the help of many SM devs, I've created an experimental Golang to SourcePawn source to source compiler aka a transpiler.

What does it do? It takes (a subset of) Golang code and converts it to an equivalent SourcePawn version, here's a quick example:

Code:
/// SourceGo
package main

const (
	a, b = "A", MAXPLAYERS
	c = a
	d string = "D"
	e = "e1"
	f = 1.00
)

var (
	myself = Plugin{
		name: "SrcGo Plugin",
		author: "Nergal",
		description: "Plugin made into SP from SrcGo.",
		version: "1.0a",
		url: "https://github.com/assyrianic/Go2SourcePawn",
	}
	
	str_array = [...]string{
		"kek",
		"foo",
		"bar",
		"bazz",
	}
)

type (
	Point struct{ x, y float }
	QAngle Vec3
	Name [64]char
	Color = [4]int
	
	PlayerInfo struct {
		Origin Vec3
		Angle QAngle
		Weaps [3]Entity
	}
	
	Kektus    func(i, x Vec3, b string, blocks *Name, KC *int)   Handle
	EventFunc func(event Event, name string, dontBroadcast bool) Action
)


func OnlyScoutsLeft(team int) bool {
	for i:=0; i<=MaxClients; i++ {
		if !IsValidClient(i) || !IsPlayerAlive(i) {
			continue;
		} else if GetClientTeam(i) == team && TF2_GetPlayerClass(i) != TFClass_Scout {
			return false
		}
	}
	return true
}


func IsClientInGame(client Entity) bool

func main() {
	for i := 1; i<=MaxClients; i++ {
		if IsClientInGame(i) {
			OnClientPutInServer(i)
		}
	}
}

func OnClientPutInServer(client Entity) {
	/// do something with client.
}
Code:
/// Generated SourcePawn:
#include <sourcemod>

char a[] = "A";
int b = MAXPLAYERS;
char c[] = a;
char d[] = "D";
char e[] = "e1";
float f = 1.00;

public Plugin myself = {
	name = "SrcGo Plugin",
	author = "Nergal",
	description = "Plugin made into SP from SrcGo.",
	version = "1.0a",
	url = "https://github.com/assyrianic/Go2SourcePawn"
};
char str_array[4][] = {
	"kek",
	"foo",
	"bar",
	"bazz"
};

enum struct Point {
	float x;
	float y;
}
enum struct PlayerInfo {
	float Origin[3];
	float Angle[3];
	int Weaps[3];
}
typedef Kektus = function Handle (const float i[3], const float x[3], const char[] b, char blocks[64], int& KC);
typedef EventFunc = function Action (Event event, const char[] name, bool dontBroadcast);


public bool OnlyScoutsLeft(int team) {
	for (int i = 0; i <= MaxClients; i++) {
		if (!IsValidClient(i) || !IsPlayerAlive(i)) {
			continue;
		}
		else if (GetClientTeam(i) == team && TF2_GetPlayerClass(i) != TFClass_Scout) {
			return false;
		}

	}
	return true;
}

native bool IsClientInGame(int client);
public void OnPluginStart() {
	for (int i = 1; i <= MaxClients; i++) {
		if (IsClientInGame(i)) {
			OnClientPutInServer(i);
		}

	}

}

public void OnClientPutInServer(int client) {
}

The transpiler itself is written in Golang and can easily be cross-compiled for Windows 32-bit, 64-bit and Linux/Mac 32-bit, 64-bit from the Go compiler directly.

The project is MIT licensed and is currently in open Alpha phase.

The purpose of this project is to help automate and abstract over many SourcePawn constructs in order to significantly improve plugin development time. Part of this is stronger typing & type abstraction and a simpler, more expressive syntax.

Project Repo.

An important thing to remember is that, with SourceGo, you're not making SourceMod plugins with Golang, you're using Golang's syntax that is then transformed into its SourcePawn equivalent code.
__________________

Last edited by nergal; 02-11-2021 at 17:42. Reason: update
nergal is offline
Domino_
AlliedModders Donor
Join Date: Jul 2016
Old 11-02-2020 , 18:01   Re: SourceGo: Experimental Golang to SourcePawn Transpiler
Reply With Quote #2

I look forward to seeing where this goes
__________________
Domino_ is offline
Mayor Gamer
Senior Member
Join Date: Nov 2012
Location: GetLocationOfUser(me);
Old 11-03-2020 , 13:32   Re: SourceGo: Experimental Golang to SourcePawn Transpiler
Reply With Quote #3

This looks pretty interesting. I've seen lots of interest with Rust nowadays, but GoLang is something I definitely would love to see having SourcePawn support.

Also looking forward to this!
__________________
Mayor Gamer is offline
nergal
Veteran Member
Join Date: Apr 2012
Old 11-03-2020 , 17:26   Re: SourceGo: Experimental Golang to SourcePawn Transpiler
Reply With Quote #4

In terms of what SourceGo is capable of, here's an example using a receiver, returning multiple values, and assigning multiple values.

Code:
type PlayerInfo struct {
	Origin Vec3
	Angle QAngle
	Weaps [3]Entity
}

func (pi PlayerInfo) GetOrigin(buffer *Vec3) (float, float, float) {
	*buffer = pi.Origin
	return pi.Origin[0], pi.Origin[1], pi.Origin[2]
}

var p PlayerInfo
var origin Vec3
x,y,z := p.GetOrigin(&origin)
origin[0], origin[1], origin[2] = x,y,z
this becomes:
Code:
enum struct PlayerInfo {
	float Origin[3];
	float Angle[3];
	int Weaps[3];
}

public float PlayerInfo_GetOrigin(const PlayerInfo pi, float buffer[3], float& PlayerInfo_GetOrigin_param1, float& PlayerInfo_GetOrigin_param2) {
	buffer = pi.Origin;
	PlayerInfo_GetOrigin_param1 = pi.Origin[1];
	PlayerInfo_GetOrigin_param2 = pi.Origin[2];
	return pi.Origin[0];
}

PlayerInfo p;
float origin[3];

float x;
float y;
float z;

x = PlayerInfo_GetOrigin(p, origin, y, z);
origin[0] = x;
origin[1] = y;
origin[2] = z;
__________________
nergal is offline
nergal
Veteran Member
Join Date: Apr 2012
Old 11-04-2020 , 23:01   Re: SourceGo: Experimental Golang to SourcePawn Transpiler
Reply With Quote #5

Update v0.20a. Ranged for-loops are now supported.

Code:
var clients [MAXPLAYERS+1]Entity
for index, client := range clients {
    /// code;
}
__________________
nergal is offline
nergal
Veteran Member
Join Date: Apr 2012
Old 11-05-2020 , 17:25   Re: SourceGo: Experimental Golang to SourcePawn Transpiler
Reply With Quote #6

another update, v0.22A, added two types of switch statements: normal and "true" switch statements.

Normal is of course what you'd expect:
Code:
/// Original:
switch x {
	case 1, 2:
	case 3:
	default:
}

/// Generated:
switch (x) {
	case 1, 2: {
	}
	case 3: {
	}
	default: {
	}
}
Golang has a feature where you can omit the controller expression, which basically makes it "true" in terms of value. Thus you have "true" switch statements which can act as a more compact form of an if-else-if series. This is also supported and appropriately generated!
Code:
/// Original:
switch {
	case x < 10, x+y < 10.0:
	case x * y <= 1024.0:
	default:
}

/// Generated:
if ((x < 10) || (x + y < 10.0)) {
}
else if ((x * y <= 1024.0)) {
}
else {
}
__________________

Last edited by nergal; 11-05-2020 at 17:26.
nergal is offline
nergal
Veteran Member
Join Date: Apr 2012
Old 11-07-2020 , 18:16   Re: SourceGo: Experimental Golang to SourcePawn Transpiler
Reply With Quote #7

alright, with version v0.25a.
Here's a sample of a plugin that modifies the mantreads damage written in "SourceGolang" and the code it generated:

Code:
package main

import (
	"sdkhooks"
)

func main() {
	for i := 1; i<=MaxClients; i++ {
		if IsClientInGame(i) {
			OnClientPutInServer(i)
		}
	}
}


func OnClientPutInServer(client Entity) {
	SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage)
}

func OnTakeDamage(victim Entity, attacker, inflictor, damagetype, weapon *Entity, damage *float, damageForce, damagePos *Vec3) Action {
	if IsValidEntity(*weapon) && GetEntProp(*weapon, Prop_Send, "m_iItemDefinitionIndex")==444 {
		*damage *= 5.0
		return Plugin_Changed
	}
	return Plugin_Continue
}
Code:
/**
 * file generated by the GoToSourcePawn Transpiler v0.25a
 * Copyright 2020 (C) Kevin Yonan aka Nergal, Assyrianic.
 * GoToSourcePawn Project is licensed under MIT.
 * link: 'https://github.com/assyrianic/Go2SourcePawn'
 */

#include <sourcemod>
#include <sdkhooks>


public void OnPluginStart() {
	for (int i = 1; i <= MaxClients; i++) {
		if (IsClientInGame(i)) {
			OnClientPutInServer(i);
		}

	}

}

public void OnClientPutInServer(int client) {
	SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage);
}

public Action OnTakeDamage(int victim, int& attacker, int& inflictor, int& damagetype, int& weapon, float& damage, float damageForce[3], float damagePos[3]) {
	if (IsValidEntity(weapon) && GetEntProp(weapon, Prop_Send, "m_iItemDefinitionIndex") == 444) {
		damage *= 5.0;
		return Plugin_Changed;
	}
	return Plugin_Continue;
}
__________________
nergal is offline
nergal
Veteran Member
Join Date: Apr 2012
Old 11-16-2020 , 22:51   Re: SourceGo: Experimental Golang to SourcePawn Transpiler
Reply With Quote #8

After exactly a week of time gone, I have finally managed to abstract function pointers to where they appropriately break down to manual function calling API:


Code:
func main() {
	CB := OnClientPutInServer
	for i := 1; i<=MaxClients; i++ {
		CB(i)
	}
}

func OnClientPutInServer(client Entity) {}
Becomes:
Code:
public void OnPluginStart() {
	Function CB = OnClientPutInServer;
	for (int i = 1; i <= MaxClients; i++) {
		Call_StartFunction(null, CB);
		Call_PushCell(i);
		Call_Finish();
	}
}

public void OnClientPutInServer(int client) {}
__________________
nergal is offline
nergal
Veteran Member
Join Date: Apr 2012
Old 02-11-2021 , 17:50   Re: SourceGo: Golang to SourcePawn Transpiler (v1.4 beta)
Reply With Quote #9

good news, SourceGo aka Go2SourcePawn, is now in open beta at version 1.4

It now has a complete SourceMod interface file for being able to use SM's natives in a Golang-way.
SourceGo also has a built-in function `__sp__` for inlining SourcePawn code that can't be replicated from SourceGo:
PHP Code:
var kv KeyValues
__sp__
(`kv = new KeyValues("config.cfg");`) 
becomes:
PHP Code:
KeyValues kv;
kv = new KeyValues("config.cfg"); 
Newest feature for 1.4 is using `make` to create dynamically sized, local arrays.
PHP Code:
my_str := make([]charsize
which would become:
PHP Code:
char[] my_str = new char[size]; 
__________________

Last edited by nergal; 02-12-2021 at 15:04. Reason: adding code as example usage.
nergal is offline
wopox3
Junior Member
Join Date: Dec 2013
Location: Russia
Old 07-18-2021 , 15:43   Re: SourceGo: Golang to SourcePawn Transpiler (v1.4 beta)
Reply With Quote #10

This looks very interesting! Is it possible to write transpiler SourcePawn -> GoLang? Is it planned?

Last edited by wopox3; 07-18-2021 at 15:43.
wopox3 is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 12:33.


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