Table of Contents

Libraries

In this tutorial, we will create a library of C# code to import into TableScript.
To create a custom library with external functions, start by creating a partial class with static or instance methods marked with the TableScriptLibrary attribute, and an appropiate filename:

using TableScript;
using TableScript.Generator;

[TableScriptLibrary("customlib.cs")]
public static partial class CustomLib{
	
}

Inside of it, you can place TableScript functions and globals. For example:

[TableScriptGlobal]
public static readonly string country = "Spain";

[TableScriptFunction]
public static int sum1(int a){
	return a + 1;
}

[TableScriptFunction]
public static string getDayOfTheWeek(int index){
	return index switch{
		1 => "Monday",
		2 => "Tuesday",
		3 => "Wednesday",
		4 => "Thursday",
		5 => "Friday",
		6 => "Saturday",
		7 => "Sunday",
		_ => null
	};
}

Fields marked with TableScriptGlobal must be declared readonly.
Properties marked with TableScriptGlobal must be read-only (no set method) and not be indexers. They will be accessed once, on first usage of the TableScriptGlobals variable.

Type casting

Because functions in TableScript always return Table and take Table as arguments, they need to be converted from and to the C# supported types.
For the methods marked as TableScriptFunction, the valid return types are:

  • void: Returns an empty Table
  • string: Returns a single element table. If the string is null, an empty table
  • int: Returns a number table (new Table(int))
  • bool: Returns a 0 or 1 element table (Table.GetBool(bool))
  • Table: No conversion is done

For the arguments, they must be one of the following:

  • string: The table argument is reduced (Table.AsString())
  • int: The table argument Length is used (Table.Length)
  • bool: The table truthiness(length > 0) is used (Table.Truthy)
  • Table: No conversion is done

Generator output

Now, the compile time source generator generates:

  • TableScriptFilename: a string containing the argument specified in TableScriptLibrary.
  • TableScriptImport: fully functional ResolvedImport.
  • TableScriptFunctions: an array of FunctionStmt.
  • TableScriptGlobals: a Dictionary<string, Table> of globals.

Importing the library

As we saw previously, we can use a custom IImportResolver.
In this example, we will implement a Resolver on top of the Standard Resolver that can resolve this new library.
This is the custom IImportResolver:

using TableScript;

class CustomImportResolver : StandardImportResolver{
	public override ResolvedImport Resolve(string import, string callingFilename){
		if(import == "customlib"){
			return CustomLib.TableScriptImport;
		}
		return base.Resolve(import, callingFilename); //Safely handle anything that wasnt recognized
	}
}

Then, we just need the Main method:

using TableScript;

class Program{
	static void Main(){
		string path = "program.tbs";
		
		try{
			Script script = Script.FromSource(path, File.ReadAllText(path), new CustomImportResolver());
			
			script.Run();
		}catch(TableScriptException ex){
			Console.Error.WriteLine(ex);
		}
	}
}

Now, using this CustomImportResolver, we will have acess to sum1, getDayOfTheWeek and country:

// IMPORTANT
// In this file, next to print() calls, the supposed output will be shown in a comment along with a commentary if needed

import stdlib;
import stdnum;
import customlib; //Our custom library!

print(sum1(3).toNum()); //4
print(getDayOfTheWeek(5)); //Friday
print(country); //Spain
Warning

Don't call your file customlib.tbs because that will generate two imports with the same name causing conflicts

Printing

If there is any doubt about the signature of functions implemented in libraries, you can always print them out:

Console.WriteLine(CustomLib.TableScriptImport);

This prints:

export global country = ["Spain"];
export function sum1(a){ EXTERN; } //Takes 1 arguments: table a as int. Returns table as int.
export function getDayOfTheWeek(index){ EXTERN; } //Takes 1 arguments: table index as int. Returns table as string.

XML comments

To support function descriptions like this:

export function sum1(a){ EXTERN; } //Takes 1 arguments: table a as int. Returns table as int. Sum 1 to a number
export function getDayOfTheWeek(index){ EXTERN; } //Takes 1 arguments: table index as int. Returns table as string. Get day of the week name by index

Just add this to your csproj:

<PropertyGroup>
	<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

And add XML descriptors to functions:

/// <summary>
/// Sum 1 to a number
/// </summary>
[TableScriptFunction]
public static int sum1(int a){
	return a + 1;
}