SGScript - description
This is a programming language that is made to be fast, accessible and simple.
include "math";
gradient = [ ".", "o", "O", "#", "O", "o", "." ];
for( y = -7; y <= 7; ++y )
{
for( x = -7; x <= 7; ++x )
{
dst = sqrt( x * x + y * y ) * 0.9;
if( dst > 6 )
dst = 6;
chr = gradient[ dst ];
print chr $ ' ';
}
println();
}
It is similar to many but the exact combination makes it unique in comparison to others. Thus, it might be best to describe it in comparison to others, especially the ones that heavily influenced the development of SGScript.
language | what it DOESN'T have in comparison to SGScript |
C | dynamic typing, built-in serialization |
Lua | built-in serialization, C-like syntax, proper indexing, arrays, ... |
PHP | consistency, lightweight design |
JavaScript | environmental awareness, determinism, built-in serialization, ... |
Python | C-like syntax, lightweight design |
With this in mind, technologies get upgraded occasionally, thus be sure to take this comparison with a grain of salt and recheck it and perhaps even report the factual errors along with the version number that marked the introduction of changes.
However, SGScript has all of the things mentioned, and some more, possibly making it one of the most balanced languages ever created.
The language supports:
if/else
, while
, for
, do/while
, foreach
- 9 variable types: null, bool, int, real, string, function, C function, object, pointer
- Multi-level break/continue
- Multiple return values
- First-class functions and ability to attach variables to functions (creating closures)
The standard library includes:
- array, dict, map, class
- math, string, I/O, O/S and formatting functions
eval
, file import, DLL import
Code samples - SGScript
Statements
print "Text";
println( "!" );
b = rand();
Comments
// this is a comment that ends with the line
/* this type of comment
can be more than
one line long
*/
Basic calculations
a = 1, b = 2, c = 5;
d = a + b * c - b / a;
a += 3.14;
c = "eye" $ "sight" // stitch (concatenate) strings together!
d = "Ocean's " $ 11;
Comparison
if( c > 5 )
print "as expected";
y = x <= 8.8; // result of comparison can be assigned!
Useful shortcuts
a += 1; // short for a = a + 1
a++; // short for a += 1
a--;
a = if( b > 5, 10, 20 ); // short for if( b > 5 ){ a = 10; } else { a = 20; }
Flow control
if( a > b )
{
print "something happens only if a is greater than b";
}
else
print "...and here the opposite is true";
while( a > b )
{
print "something happens as long as a is greater than b";
a--; // but not for too long, as we see
}
// or maybe ...
do
{ // first we do
print a;
}
while( a++ < 10 ); // then we check
More useful shortcuts
for( i = 0; i < 10; i++ )
print i;
// .. is the short form for ..
i = 0;
while( i < 10 )
{
print i;
i++;
}
for(;;) // this is not going to stop...
print "x";
More flow control
x = 5;
for(;;)
{
print x;
x--;
if( x < 0 )
break; // this says that we don't want to continue staying in the loop
}
// << this is where "break" leads us, right after the loop
// this goes through a list
foreach( fruit : [ "apple", "orange", "banana" ] )
println( fruit );
// .. of 2 items ..
list = { "1" = "apple", "2" = "orange", "3" = "banana" };
foreach( number, fruit : list )
println( number $ ". " $ fruit );
Functions
// cornerstore of reusable code
function square( x )
{
return x * x;
}
print square( 5 );
function print_quoted( text )
{
print '"' $ text $ '"';
}
print_quoted( "It works!" );
Objects
a = [ 1, 2, "three" ];
a[2] = 3;
a[1]++;
d = {
name = "test",
text = "hello",
};
d.name = "test, edited";
d.text $= ", world!";
println( d.text ); // hello, world!
Interesting stuff
printvar( x ); // tells you all you want to know about "x"
// emits an error with the given message if the first argument is false
assert( x > 5, "x must be greater than 5" );
// returns the type name
typeof( x );
// universal external code loader
include "math", "string", "something";
Code samples - the C API
Primary operations
// create the context
sgs_Context* C = sgs_CreateEngine();
// load the built-in math library
sgs_LoadLib_Math( C );
// load a file
sgs_ExecFile( C, "script.sgs" );
// call a global function with 0 arguments, expecting 0 values returned
sgs_GlobalCall( C, "myFunction", 0, 0 );
// destroy the context
sgs_DestroyEngine( C );
Data in, data out
sgs_Context* C = sgs_CreateEngine();
sgs_LoadLib_Math( C );
// push a variable on the stack
sgs_PushReal( C, 3.14 );
// call a global function with 1 argument, expecting 1 value returned
sgs_GlobalCall( C, "sin", 1, 1 );
// check the returned value
printf( "returned value: %f\n", sgs_GetReal( C, -1 ) );
// clean the stack
sgs_SetStackSize( C, 0 );
Variable types
SGScript has 8 primary variable types:
null
: the 'lack of a better value' type
bool
: boolean, true/false
int
: signed integer
real
: floating point number
string
: byte buffer
(SGS) function
: function that was defined in and compiled from SGScript code
C function
: function defined in C code
object
: the extension type and container for complex built-in types
Extended variable types (built on object
):
array
: a dynamically allocated variable array
dict
: a map/table structure where variables are mapped to string keys
map
: a map/table structure where variables are mapped to variable keys
class
: object that uses two other objects to build its interface
closure
: a callable object consisting of another callable and several variables
Conversion rules
from \ to | bool | int | real | string | ptr |
null | false | 0 | 0.0 | "null" | NULL |
bool | - | 0/1 | 0.0/1.0 | "false"/"true" | NULL/0x1 |
int | 0 => false, otherwise true | - | - | - | cast |
real | 0.0 => false, otherwise true | round to nearest | - | sprintf %g | cast |
string | empty => false, otherwise true | *1 | *1 | - | char* |
func | true | 0 | 0.0 | "function" | NULL |
cfunc | true | 0 | 0.0 | "C function" | NULL |
object *2 | true | 0 | 0.0 | "object" | data ptr. |
ptr | NULL => false, otherwise true | cast | cast | sprintf ptr(%p) | - |
- "-" means the conversion is not necessary, does not affect data or the effect of conversion should be immediately obvious
- *1) see Numeric string parsing rules for more info
- *2) these are the default values, overrides can be provided in CONVERT function and type name for string
Code structure
Code can contain constants, identifiers, expressions and statements. Statements usually include expressions but expressions can also include statements, specifically - function expressions.
Constants
Available constant formats:
type | subtype | examples |
null | - | null |
bool | - | true, false |
int | decimal | 1413, -583, 0 |
int | binary | 0b0101, 0b11 |
int | octal | 0o644, 0o1, 0o77 |
int | hexadecimal | 0x1f, 0xCA5 |
real | basic | 0.14, -25.48 |
real | scientific | 1.5e-5, 1e+10 |
string | normal | "text", '1\n2' |
string | unescaped* | """text""", '''1\2''' |
*) unescaped strings don't parse their contents at all, and the ending markers (""" or ''') cannot be escaped
Identifiers
Identifiers can contain letters (a-z, A-Z), numbers (0-9) or underscores ("_") but they cannot begin with a number.
Special keywords and hardcoded constants:
name | type | usage |
this | special identifier, read-only | method context retrieval |
_G | special identifier, read/write | global environment access |
null | constant | constant |
true | constant | constant |
false | constant | constant |
var | restricted keyword | variable declaration |
global | restricted keyword | variable declaration |
function | restricted keyword | function definition |
use | restricted keyword | function definition |
if | restricted keyword | "if" statement |
else | restricted keyword | "if/else" statement |
do | restricted keyword | "do/while" statement |
while | restricted keyword | "while", "do/while" statements |
for | restricted keyword | "for" statement |
foreach | restricted keyword | "foreach" statement |
break | restricted keyword | "break" statement |
continue | restricted keyword | "continue" statement |
return | restricted keyword | "return" statement |
Expressions
Expressions can be categorized in many different ways: type of action, appearance, whether it also assigns the value somewhere or if its purpose has a special meaning.
There are 5 types of action for expressions in SGScript: arithmetic, binary, boolean, comparison and special.
expression | appearance | type of action | assign | # in. |
add | A + B | arithmetic | no | 2 |
subtract | A - B | arithmetic | no | 2 |
multiply | A * B | arithmetic | no | 2 |
divide | A / B | arithmetic | no | 2 |
modulo | A % B | arithmetic | no | 2 |
pre-increment | ++ A | arithmetic | self | 1 |
pre-decrement | -- A | arithmetic | self | 1 |
post-increment | A ++ | arithmetic | self | 1 |
post-decrement | A -- | arithmetic | self | 1 |
add-assign | A += B | arithmetic | yes | 2 |
subtract-assign | A -= B | arithmetic | yes | 2 |
multiply-assign | A *= B | arithmetic | yes | 2 |
divide-assign | A /= B | arithmetic | yes | 2 |
modulo-assign | A %= B | arithmetic | yes | 2 |
binary AND | A & B | binary | no | 2 |
binary OR | A | B | binary | no | 2 |
binary XOR | A ^ B | binary | no | 2 |
left shift | A << B | binary | no | 2 |
right shift | A >> B | binary | no | 2 |
binary AND-assign | A &= B | binary | yes | 2 |
binary OR-assign | A |= B | binary | yes | 2 |
binary XOR-assign | A ^= B | binary | yes | 2 |
left shift-assign | A <<= B | binary | yes | 2 |
right shift-assign | A >>= B | binary | yes | 2 |
binary invert | ~ A | binary | no | 1 |
boolean AND | A && B | boolean | no | 2 |
boolean OR | A || B | boolean | no | 2 |
boolean AND-assign | A &&= B | boolean | yes | 2 |
boolean OR-assign | A ||= B | boolean | yes | 2 |
boolean invert | ! A | boolean | no | 1 |
less than | A < B | comparison | no | 2 |
less than or equal | A <= B | comparison | no | 2 |
greater than | A > B | comparison | no | 2 |
greater than or equal | A >= B | comparison | no | 2 |
equal | A == B | comparison | no | 2 |
not equal | A != B | comparison | no | 2 |
strict equality | A === B | comparison | no | 2 |
strict inequality | A !== B | comparison | no | 2 |
raw comparison | A <=> B | comparison | no | 2 |
error suppression | @ A | special | no | 1 |
declare-local | var A | special | maybe | any |
declare-global | global A | special | maybe | any |
array literal | [ A, B, .. ] | special | no | any |
dict. literal | {A=1,B=2,..} | special | no | any |
assign | A = B | special | yes | 1 |
concatenate | A $ B | special | no | 2 |
concatenate-assign | A $= B | special | yes | 2 |
property | A . B | special | maybe | 2 |
index | A [ B ] | special | maybe | 2 |
multi-index-assign | A[]<dict.lit> | special | yes | any |
multi-property-assign | A.<dict.lit> | special | yes | any |
function call | A ([B,..]) | special | no | <=256 |
comp. function call | O!A ([B,..]) | special | no | <=256 |
function definition | function A.. | special | maybe | 0 |
inline if | if(A,B,C) | special | no | 3(2) |
subexpression | ( A[, ..] ) | special | maybe | any |
Some notes on the special cases:
- [increment,decrement] pre-increment and pre-decrement operators return the modified value, post- operators - the original one
- [boolean] all boolean operators except 'boolean invert' (which returns bool) set/return one of the two operands passed
- [equality] strict (in)equality operators are the same as their non-strict counterparts with one difference: they do type checking, for example
5 == 5.0
would return 'true' and 5 === 5.0
would return 'false'
- [declare] declarations only actually set the data if they include the assignment expression, otherwise only the type is internally noted for other references
- [declare] variables can be redeclared as long as they maintain their access level
- [property,index] whether property or index expressions set data depends if they're on the receiving (left) end of an assignment expression
- [inline if] 3 inputs are required, 2 are actually used (as if
if(A){return B;}else{return C;}
was used)
- [subexpression] subexpressions can set data if they are set up like this: <subexpression> = <function-call> - this is the way to read more than one return value from a function
- [error suppression] the
@
operator disables warnings, errors and any other messages for as long as the subexpression is executed, this is mostly useful for things like reading a property or calling a function that may not exist, in cases where that isn't an error
- [function] the full function definition expression syntax:
function <name> ( <args> ) [ use ( <use-list> ) ]
, followed by either { ... }
or = ... ;
. <name>, <args> and the 'use' block are all optional.
- [multi-set] operator returns
A
, that is, the object itself
compatible function call / inheritance call / global method call ( O!A ([B,..])
)
CFC is created to encourage users to reduce memory usage without sacrificing clarity of code. It is a short-hand, optimized version of the .call method / sys_call function for callables.
Properties:
- uses the same symbol as boolean inversion operator
- usage: simplified & optimized calling of non-integrated compatible functions
- instead of
comp_func.call( object, arg1 )
write object!comp_func( arg1 )
- instead of putting functions with data / class interfaces, requiring pointless memory usage, allows to easily keep them separate
- simplify inheritance-like code models to the extent permitted by a dynamic language
Example WITHOUT:
function create_object()
{
object = { x = 0, y = 0 };
function object.move( x, y ){ this.x = x; this.y = y; @this.move_callback(); }
function object.tick( delta ){ this.move( this.x + delta, this.y ); }
return object;
}
Example WITH:
function Object_Move( x, y ){ this.x = x; this.y = y; @this.move_callback(); }
function create_object()
{
object = { x = 0, y = 0 };
function object.tick( delta ){ this!Object_Move( this.x + delta, this.y ); }
return object;
}
Now, by itself it may not mean much, however let's see what happens if the following code is used:
for( i = 0; i < 100; ++i )
objects.push( create_object() );
Without the usage of a global method, there's a key 'move' in each object that points to the function. In real software there may be no less than 10 such keys in many instances of many objects. And if there are no overrides planned for it, there's no need for it to be there but we can't really move it. Classes are an option that involves a few more allocations and it requires more memory to use them. Using .call/sys_call
or replacing this
with an argument would sacrifice readability and the option to relocate functions, as well as performance, this being a double call. This is where CFC comes in - syntax allows to clearly state the object and function used, and the required interface for the object to be compatible with said function.
Statements
There are 4 statement types in SGScript:
Container statements
There are two types of container statements: expression statements and block statements.
- Expression statements contain zero or more expressions, separated by commas (",") and ending with semicolons (";").
- Block statements contain zero or more statements.
Format:
- expression statement:
<expression>[, <expression>[, <expression> ...]] ;
- block statement:
{ [<statement>[, <statement>...]] }
Examples:
a = 5;
a = 1, b = 2;
Flow control statements
These statements decide which code gets executed when. They include loops (while, for, foreach, do/while), the if/else construct, break/continue/return.
Formats:
- if/else:
if( <expression> ) <statement> [ else <statement> ]
- while:
while( <expression> ) <statement>
- for:
for( <expression-list>; <expression-list>; <expression-list> ) <statement>
- foreach:
foreach( [<identifier>,][<identifier>] : <expression> ) <statement>
- do/while:
do <statement> while( <expression> )
- break:
break <N>;
- continue:
continue <N>;
- return:
return <expression-list>;
Examples:
if( a )
{
print( "a is true" );
}
else
print( "a is not true" );
while( b > 0 ) b--;
Declaration statements
Statements that begin with "var", "global" or "function" declare and set variables.
Examples:
var x = 5, y = 6, z;
global World = null;
function fn(){ INFO( "'fn' was called" ); }
Function call statements
These statements are converted directly to function calls. Currently, 'include' and 'print' functions are available as statements.
Formats:
- include:
include [<file1>[, <file2>...]];
- for each entry, a function call is generated
- print:
print [<string>[, <string>...]];
- one function call is generated for all items
Examples:
include "io", "string";
print "Count: ", count;
Built-in accessors
There are several built-in accessors for the variable types that are available.
name | variable type | accessor type | description |
length | string | property | returns the length of the string, in bytes |
char. at | string | index | returns the character from the specified position |
call | any callable | property | function that allows to specify "this" for the call |
Common constructs in SGScript
This section shows some ways of implementing various often-used constructs in SGScript. Some of them (specifically the constructs coming from compiled languages) do not map directly to any set of native features and are considered solutions of lower quality.
Basic classes
global SampleClass = {}; // create a placeholder type dictionary
function SampleClass.SampleMethod( a, b ) // this is the name that will show up in debug output
{
return a + b + this.c; // usage of "this" turns the function into a method
}
function SampleClass.SampleFunction( a, b )
{
return a + b;
}
// Function will show up as "<anonymous>" in debug output, so avoid this kind of function declaration if possible
SampleClass.SampleAnonymous = function( a, b )
{
return a + b + this.c;
}; // <-- the semicolon is required for this notation
// Giving functions a specific name:
function MyCustomFunction( a, b )
{
return a + b + this.c; // note that it is still possible to use "this"
}
SampleClass.Sample = MyCustomFunction;
SampleClass.StaticVariable = 5;
// class instantiation without custom data
myclass = class( {}, SampleClass );
// class instantiation with custom data
CustomData = { c = 5, d = 6 };
mydataclass = class( CustomData, SampleClass );
// static construction function
function SampleClass.Create( x )
{
data = { c = x };
return class( data, SampleClass );
}
// make class interface into a construction function
function SampleClass.__call( x )
{
return SampleClass.Create( x );
}
SampleClass = class( null, SampleClass );
// Be aware that this method involves some runtime overhead.
// Prefer simply giving the construction function (or the interface variable) a different name:
function createSampleClass( x )
{
data = { c = x };
return class( data, SampleClass );
}
// destructor
function SampleClass.__destruct()
{
this.c = null;
}
// many more special methods are available for 'class' objects
Inheritance
// class A - base class
global A = {};
function A.func()
{
println( "base" );
}
function A.create()
{
return class( {}, A );
}
// class B - inherits from A
global B = {};
function B.func()
{
// needless to say, this is not the preferred way to do software design in SGScript
this._super._super.func.call( this );
println( "override" );
}
A.func_A = A.func; // make a duplicate entry that will not be overridden
// it is usually preferred to make the duplicates near the original entries where they're expected to be overridden
function B.func()
{
B.func_A(); // call that entry instead of the original, obstructed entry
println( "override" );
}
function B.create()
{
return class( {}, class( B, A ) );
}
Game entities
With game entities and objects of similar structure (just about any object) it is easier to simply define it as a key-value data map, without any classes, inheritance or anything of that kind. The nature of a dynamically typed scripting engine implies that almost everything is checked at runtime, making emulation of compiled language constructs pointless.
entity =
{
x = 10,
y = 20,
};
function entity.tick( dt )
{
this.x += dt;
}
Numeric string parsing rules
">>>" means "until any other symbol has been found" (the text is too dense for exact repetition)
The string is not a number if no numeric characters (0-9) could be parsed. (for example, "+" isn't a number but "0x" is)
- if string begins with 0b and has at least 3 characters, try to read a binary integer
- >>>, 0 or 1 adds the specified bit to the integer
- if string begins with 0o and has at least 3 characters, try to read an octal integer
- >>>, characters 0-7 add the specified 3 bits to the integer
- if string begins with 0x and has at least 3 characters, try to read a hexadecimal integer
- >>>, characters 0-9, a-f and A-F add the specified 4 bits to the integer
- otherwise, try to read a decimal number
- do a test to see if the number is not an integer
- skip the sign character (+ or -)
- skip the 0-9 characters
- if e, E or . is found, try to read a real value
- read the sign character (+ or -)
- >>>, characters 0-9 add the specified decimal number to the whole part
- if the dot character (.) is found, read the fractional part
- >>>, characters 0-9 add the specified decimal number to the fractional part
- if at least 3 more characters can be found and the first is "e" or "E", read the exponent part
- read the sign character (+ or -)
- >>>, characters 0-9 add the specified decimal number to the exponent part
- otherwise, try to read the integer
- read the sign character (+ or -)
- >>>, characters 0-9 add the specified decimal number to the integer
C API reference
The interface that it defines is one of the driving forces of SGScript. It is heavily influenced by Lua, while also adding some features of PHP (Zend Engine) and Python.
The most important difference is in error handling and triggers: errors detected in C can easily be non-fatal. Just like with PHP, minor errors are emitted as warnings that also propagate invalid (null) values throughout the system to effectively disable the subsequent calls and notify whoever is interested of the exact trail of errors. Furthermore, this behavior can be modified by using protected calls (pcall function) in SGScript and custom messaging callbacks in C.
The virtual machine supports:
- Operator overloading
- On-demand garbage collection
- Full introspection of machine state
- Type registration for simplified cross-library data reuse
Constants and types
This part of the documentation describes the various types and definitions used in the C API.
Main types
Return types:
- SGSRESULT [int]: output code (success = 0, failure: < 0 )
- SGSBOOL [int]: simplified output code (success = 1, failure = 0)
- SGSMIXED [int32_t] output code / value (success + value: >= 0, failure: < 0)
Virtual machine / language types:
- sgs_Bool [int32_t]: boolean value
- sgs_Int [int64_t]: integer
- sgs_Real [double]: real (floating point) value
- sgs_SizeVal [int32_t]: size type
- sgs_CFunc [int ( sgs_Context* )]: C function type
- sgs_ObjInterface [struct]: object interface description
- sgs_Variable [struct]: the combined variable type
System types:
- sgs_Context [struct]: the virtual machine
- sgs_StackFrame [struct]: the function call info object
Interface types:
- sgs_MemFunc [void* ( void* userdata, void* ptr, size_t size )]: memory interface function
- sgs_OutputFunc [void ( void* userdata, sgs_Context* C, const void* buf, sgs_SizeVal size )]: output function
- sgs_MsgFunc [void ( void* userdata, sgs_Context* C, int code, const char* text )]: messaging function
- sgs_HookFunc [void ( void*, sgs_Context*, int )]: debug hook function
Error codes
These are the default meanings for error codes that are honored throughout the API.
- Generated by the C API
- SGS_SUCCESS: operation was successful
- SGS_ENOTFND: item was not found
- SGS_ECOMP: compile error
- SGS_ENOTOBJ: argument was not an object
- SGS_ENOTSUP: operation is not supported
- SGS_EINVAL: invalid value was passed
- SGS_EINPROC: process was interrupted
- Generated by SGScript VM
- SGS_INFO: information about potential issues and state of the system
- SGS_WARNING: non-fatal issues
- SGS_ERROR: fatal issues
- any other integer may be defined and returned by other interfaces
Variable types
-- SGS_VT_[NULL|BOOL|INT|REAL|STRING|FUNC|CFUNC|OBJECT|PTR]
Constant registration types
- struct sgs_RegFuncConst { char* name; sgs_CFunc value; }
- struct sgs_RegIntConst { char* name; sgs_Int value; }
- struct sgs_RegRealConst { char* name; sgs_Real value; }
Messaging system
Messages are combinations of importance code and a null-terminated string that holds the message itself. The messaging system's purpose generally is to notify about problems and allow handling them to some extent.
The C API has a function for sending messages - sgs_Msg - and two for dealing with the current callback - sgs_SetMsgFunc / sgs_GetMsgFunc.
The sgs_Msg function basically generates the full string from the format string and calls the callback that is currently set. Due to the data association and accessibility, various systems can be implemented on top of it:
Logging
All messages can simply be logged. For the most simple approach, the sgs_StdOutputFunc callback can be used with any FILE* for the data pointer.
A limited amount of exception handling
This system can be used to break out of any point in SGS code up until the last C function. For this, pcall can be used together with a callback that calls sys_abort when necessary.
Debugging
On each warning or error, debugging code can be triggered. It can be an interactive console debugger (as implemented in ext/sgs_idbg), it could also be code that dumps the relevant state and sends it to the developer.
Hidden data collection
Similarly to exception handling, pcall can be used also for gathering messages otherwise skipped by the system. The sub-zero importance range is generally hidden - there's 2^31 values to use to mark special messages - however, sys_replevel or sgs_Cntl with SGS_CNTL_(SET_)MINLEV must be used to enable that range.
Iterator system
Iterators are objects that enable sequential, ordered traversal of object contents, allowing to read up to 2 variables at each position: the key and the value.
The C API has several functions used to deal with iterators. There are essentially three kinds of functions: initialization ( sgs_PushIterator(P), sgs_GetIterator(P) ), advancing ( sgs_IterAdvance(P) ) and data retrieval ( sgs_IterPushData(P), sgs_IterGetData(P) ).
Iterator starts at the pre-first position (-1 in terms of indices), so nothing can be read initially, before the first advance. This allows to implement iterator handling with rather simple code:
initialize;
while( advance > 0 )
{
retrieve key and/or value;
..do something else..;
}
free;
A more real example follows:
// assuming iterable object is at the top of the stack
sgs_PushIterator( C, -1 );
while( sgs_IterAdvance( C, -1 ) > 0 )
{
sgs_StackIdx ssz = sgs_StackSize( C );
sgs_IterPushData( C, -1, 1, 1 ); // push both key and value
sgs_SetStackSize( C, ssz ); // restore stack to have iterator at -1 again
}
sgs_Pop( C, 1 ); // pop the iterator
Another example using pointers:
sgs_Variable iterator, iterable, key, value;
// .. assuming iterable is initalized here ..
sgs_GetIteratorP( C, &iterable, &iterator );
while( sgs_IterAdvanceP( C, &iterator ) > 0 )
{
sgs_IterGetDataP( C, &iterator, NULL, &value );
// .. use value ..
sgs_Release( C, &value );
sgs_IterGetDataP( C, &iterator, &key, &value );
// .. use key and value ..
sgs_Release( C, &key );
sgs_Release( C, &value );
}
sgs_Release( C, &iterator );
// .. release the iterable or not, depending on how it was initialized ..
Garbage collection system
The garbage collector currently implemented is a basic stop-the-world mark-and-sweep algorithm that goes over all objects and recursively marks them as available.
The marking is done on the variable named redblue
, which contains 0 or 1 and in all avaiable objects is synced with the same variable for the context. On each pass, the bit is flipped for all available objects, so all objects that didn't have the bit flipped can be safely removed.
The garbage collector is invoked with sgs_GCExecute in the C API and gc_collect in SGScript.
Sub-objects are marked as available in the GCMARK callback with sgs_GCMark(Array) / sgs_ObjGCMark functions.
Classes
Classes are objects that enable operator/interface overloading and two-layer index retrieval.
Overloadable operators/interfaces:
- basic math: +, - (both unary and binary), *, /, %
- comparison
- conversions to bool, int, real, string
- typeof string retrieval
- cloning
Two-layer index retrieval is simply trying to read the index from a different source if the first source fails to come up with something. In other languages, metatable and prototype is the name of a table that is the second source. This allows to avoid storing functions and other data that is equal to all instances of some object type.
Closures
Closures are a combination of one callable and some variables. They are meant to simplify interfaces and code around places where it was important for functions to have access to call-invariant (same on every call) data.
Closures can be created from both SGScript and the C API, though both options have their limitations.
- In SGScript, closures can be created by letting functions "use" a variable, e.g. by writing
function func( args ) use( closures ){ ..body.. }
- In the C API, closures can be created with sgs_MakeClosure, though this requires knowledge about the receiving function's ability to use them. This means that even though there are no variable type limits, it is more practical to create closures from native functions (both plain and object interface functions) with the C API. Though prefer objects for callables if function-data bindings are necessary at the native code level.
Closure stack in the C API is technically very similar to main stack, with one important difference - functions do not accept negative indices.
Memory management
- sgs_DefaultMemFunc - example memory management callback
- sgs_Memory - allocate/reallocate/free memory
- sgs_Malloc - allocate specified amount of memory
- sgs_Free - free a previously allocated memory pointer
- sgs_Realloc - allocate/reallocate/free memory (requires implicit sgs_Context* C)
- sgs_Alloc - allocate object (requires implicit sgs_Context* C)
- sgs_Alloc_n - allocate an array of objects (requires implicit sgs_Context* C)
- sgs_Alloc_a - allocate object + additional memory (requires implicit sgs_Context* C)
- sgs_Dealloc - free a previously allocated memory pointer (requires implicit sgs_Context* C)
Execution control
- sgs_FCallP - call variable as function
- sgs_CallP - call variable as function without
this
passed to it
- sgs_ThisCallP - call variable as function function with
this
passed to it
- sgs_FCall - call the topmost stack item as function
- sgs_Call - call the topmost stack item as function without
this
passed to it
- sgs_ThisCall - call the topmost stack item as function with
this
passed to it
- sgs_GlobalCall - call a global function
- sgs_Abort - abort the execution of the previous SGS functions up to the last C function before them
- sgs_Cntl - set and/or retrieve various states in the system
Variable initialization
- sgs_InitNull - initialize variable to a null variable
- sgs_InitBool - initialize variable to a boolean variable
- sgs_InitInt - initialize variable to an integer
- sgs_InitReal - initialize variable to a real value
- sgs_InitStringBuf - initialize variable to a new char buffer
- sgs_InitString - initialize variable to a new string
- sgs_InitCFunction - initialize variable to C function
- sgs_InitObject - initialize variable to a new object
- sgs_InitObjectIPA - initialize variable to a new object with additional memory allocated in-place for the internal data pointer
- sgs_InitPtr - initialize variable to a pointer variable
- sgs_InitObjectPtr - initialize variable to an existing object and acquire it
- sgs_InitArray - initialize variable to a new array, optionally using the specified number of pushed items on stack
- sgs_InitDict - initialize variable to a new dict, optionally using the specified number of pushed items on stack
- sgs_InitMap - initialize variable to a new map, optionally using the specified number of pushed items on stack
Stack primary interface
- sgs_PushNull - push a null variable
- sgs_PushBool - push a boolean variable
- sgs_PushInt - push an integer
- sgs_PushReal - push a real value
- sgs_PushStringBuf - push a new string from char buffer
- sgs_PushString - push a new string
- sgs_PushCFunction - push a C function
- sgs_PushObject - push a new object
- sgs_PushObjectIPA - push a new object with additional memory allocated in-place for the internal data pointer
- sgs_PushPtr - push a pointer
- sgs_PushObjectPtr - push an object pointer
- sgs_PushArray - push a new array variable, optionally using the specified number of pushed items on stack
- sgs_PushDict - push a new dict variable, optionally using the specified number of pushed items on stack
- sgs_PushMap - push a new map variable, optionally using the specified number of pushed items on stack
- sgs_PushVariable - push the specified variable
- sgs_StoreVariable - retrieve, acquire and pop the topmost variable on stack
- sgs_PushItem - retrieve and push the specified variable on stack
- sgs_StoreItem - store and pop the topmost variable to the specified position after removal in stack
- sgs_InsertVariable - insert a variable on stack in the specified position
- sgs_Pop - pop the specified number of items from stack
- sgs_PopSkip - pop the specified number of items from stack, skipping some topmost items
- sgs_StackSize - return the size of the current stack frame
- sgs_SetStackSize - resize the current stack frame
- sgs_AbsIndex - convert stack index to positive if possible (if it's <0 or >=StackSize, then it's invalid)
- sgs_IsValidIndex - check if specified stack index is valid
- sgs_PeekStackItem - retrieve without acquisition the specified variable on stack
- sgs_GetStackItem - retrieve and acquire the specified variable on stack
- sgs_SetStackItem - assign variable to the specified variable on stack
- sgs_ItemType - return the variable type of the specified variable on stack
- sgs_LoadArgsExtVA - parse the stack as an argument list with additional options (for custom wrapper functions)
- sgs_LoadArgsExt - parse the stack as an argument list with additional options
- sgs_LoadArgs - parse the stack as an argument list
- sgs_ParseMethod - the
this
object variable handling function, using the macro is preferred to this
- SGS_PARSE_METHOD - automagically handle a
this
object variable regardless of the way its passed
- sgs_Method - unhide the first variable on stack if there is a hidden
this
variable
- sgs_HideThis - hide the first variable on stack if the stack already doesn't contain a hidden
this
variable
- sgs_ForceHideThis - hide the first variable even if it wasn't previously hidden before unhiding
Argument handling
- sgs_ArgErrorExt - emit an argument type mismatch error with additional formatting options
- sgs_ArgError - emit an argument type mismatch error
- sgs_FuncArgError - emit an argument type mismatch error (alias for states where
this
variable is hidden)
- sgs_MethodArgError - emit an argument type mismatch error (alias for states where
this
variable is NOT hidden)
- sgs_LoadArgsExtVA - parse the stack as an argument list with additional options (for custom wrapper functions)
- sgs_LoadArgsExt - parse the stack as an argument list with additional options
- sgs_LoadArgs - parse the stack as an argument list
- sgs_ParseMethod - the
this
object variable handling function, using the macro is preferred to this
- SGS_PARSE_METHOD - automagically handle a
this
object variable regardless of the way its passed
- sgs_Method - unhide the first variable on stack if there is a hidden
this
variable
- sgs_HideThis - hide the first variable on stack if the stack already doesn't contain a hidden
this
variable
- sgs_ForceHideThis - hide the first variable even if it wasn't previously hidden before unhiding
Virtual machine operations
- sgs_Assign - release the current variable and acquire-assign to it from the source
- sgs_ArithOp - run an arithmetic operation (+,-,*,/,%) on two variables to generate a third one
- sgs_IncDec - increment or decrement the specified variable
- sgs_Compare - check if both variables compare equal to each other
- sgs_EqualTypes - check if both variables have the same type and object interface (if both are objects)
- sgs_TypeOf - convert the topmost variable on stack to a type name string
- sgs_DumpVar - convert the topmost variable on stack to a string that contains detailed info about its contents
- sgs_GCExecute - run the garbage collection system to remove all unreachable objects
- sgs_StringConcat - concatenate two or more variables into a string
- sgs_CloneItem - clone the topmost stack item if it's mutable
- sgs_ObjectAction - execute actions on object variable on stack
- sgs_Serialize - serialize the topmost variable on stack by converting it recursively to an instruction stream
- sgs_SerializeObject - emit a call to the specified function to the serialized stream
- sgs_Unserialize - unserialize the topmost variable on stack by running its serialized instruction stream
String helpers
- sgs_PadString - return a string with two spaces appended to all newline characters
- sgs_ToPrintSafeString - return a string with all non-printable (except space), non-ASCII characters converted to a character hex code
- sgs_StringConcat - concatenate two or more variables into a string
Closure handling
- sgs_ClPushNulls - push a number of empty closures to the closure stack
- sgs_ClPushItem - push a variable on stack as a closure to the closure stack
- sgs_ClPop - pop a number of closures from the closure stack
- sgs_MakeClosure - make a callable closure object from the specified callable and number of closures on stack
- sgs_ClGetItem - retrieve the variable from a closure on stack
- sgs_ClSetItem - set the variable to a closure on stack
Data retrieval & conversion
- sgs_GetBoolP - return the boolean version of the variable
- sgs_GetIntP - return the integer version of the variable
- sgs_GetRealP - return the real value version of the variable
- sgs_GetPtrP - return the pointer version of the variable
- sgs_ToBoolP - convert variable to a boolear value and return it
- sgs_ToIntP - convert variable to an integer and return it
- sgs_ToRealP - convert variable to a real value and return it
- sgs_ToPtrP - convert variable to a pointer and return it
- sgs_ToStringBufP - convert variable to a string, returning size
- sgs_ToStringP - convert variable to a string
- sgs_ToStringBufFastP - convert variable to a string, preventing possible recursion and returning size
- sgs_ToStringFastP - convert variable to a string, preventing possible recursion
- sgs_IsObjectP - check if variable is an object and has the specified interface pointer
- sgs_IsTypeP - check if variable is of specified registered type
- sgs_IsCallableP - check if variable is callable (SGS function, C function or object with CALL impl.)
- sgs_ParseBoolP - validate conversion, optionally return boolean value from variable, if possible
- sgs_ParseIntP - validate conversion, optionally return integer value from variable, if possible
- sgs_ParseRealP - validate conversion, optionally return real value from variable, if possible
- sgs_ParseStringP - validate conversion, optionally return string or buffer from variable, if possible
- sgs_ParseObjectPtrP - validate conversion, optionally return object pointer from variable, if possible
- sgs_ParsePtrP - validate conversion, optionally return pointer from variable, if possible
- sgs_ArraySizeP - retrieve size of array variable, if possible
- sgs_GetBool - return the boolean version of the variable on stack
- sgs_GetInt - return the integer version of the variable on stack
- sgs_GetReal - return the real value version of the variable on stack
- sgs_GetPtr - return the pointer version of the variable on stack
- sgs_ToBool - convert variable on stack to a boolear value and return it
- sgs_ToInt - convert variable on stack to an integer and return it
- sgs_ToReal - convert variable on stack to a real value and return it
- sgs_ToPtr - convert variable on stack to a pointer and return it
- sgs_ToStringBuf - convert variable on stack to a string, returning size
- sgs_ToString - convert variable on stack to a string
- sgs_ToStringBufFast - convert variable on stack to a string, preventing possible recursion and returning size
- sgs_ToStringFast - convert variable on stack to a string, preventing possible recursion
- sgs_IsObject - check if variable on stack is an object and has the specified interface pointer
- sgs_IsType - check if variable on stack is of specified registered type
- sgs_IsCallable - check if variable on stack is callable (SGS function, C function or object with CALL impl.)
- sgs_ParseBool - validate conversion, optionally return boolean value from variable on stack, if possible
- sgs_ParseInt - validate conversion, optionally return integer value from variable on stack, if possible
- sgs_ParseReal - validate conversion, optionally return real value from variable on stack, if possible
- sgs_ParseString - validate conversion, optionally return string or buffer from variable on stack, if possible
- sgs_ParseObjectPtr - validate conversion, optionally return object pointer from variable on stack, if possible
- sgs_ParsePtr - validate conversion, optionally return pointer from variable on stack, if possible
- sgs_ArraySize - retrieve size of array variable on stack, if possible
- sgs_GlobalBool - retrieve global by name as bool
- sgs_GlobalInt - retrieve global by name as integer
- sgs_GlobalReal - retrieve global by name as real
- sgs_GlobalStringBuf - retrieve global by name as string buffer
- sgs_GlobalString - retrieve global by name as string
- sgs_GetStringPtrP - get string pointer from variable pointer
- sgs_GetStringSizeP - get string size from variable pointer
- sgs_GetObjectStructP - get object pointer from variable pointer
- sgs_GetObjectDataP - get data pointer of object variable pointer
- sgs_GetObjectIfaceP - get interface pointer of object variable pointer
- sgs_SetObjectDataP - set data pointer of object variable pointer
- sgs_SetObjectIfaceP - set interface pointer of object variable pointer
- sgs_GetStringPtr - get string pointer from variable on stack
- sgs_GetStringSize - get string size from variable on stack
- sgs_GetObjectStruct - get object pointer from variable on stack
- sgs_GetObjectData - get data pointer of object variable on stack
- sgs_GetObjectIface - get interface pointer of object variable on stack
- sgs_SetObjectData - set data pointer of object variable on stack
- sgs_SetObjectIface - set interface pointer of object variable on stack
Variable ownership
- sgs_Acquire - increment reference count of a variable if the type implements reference counting
- sgs_AcquireArray - acquire an array of variables
- sgs_Release - decrement reference count and possibly destroy a variable if the type implements ref.counting
- sgs_ReleaseArray - release an array of variables
- sgs_GCMark - mark a variable as available to prevent GC from removing it
- sgs_GCMarkArray - mark an array of variables as available
- sgs_ObjAcquire - acquire an object variable by its sgs_VarObj pointer
- sgs_ObjRelease - release an object variable by its sgs_VarObj pointer
- sgs_ObjGCMark - mark an object variable by its sgs_VarObj pointer
- sgs_ObjAssign - assign object pointer, handling acquisition/release properly
- sgs_ObjCallDtor - call the destruction function of an object variable if it's defined
String32 optimization interface
sgs_CreateEngine [function alias]
sgs_Context* sgs_CreateEngine()
returns a new scripting engine context
- alias to
sgs_CreateEngineExt( sgs_DefaultMemFunc, NULL )
sgs_CreateEngineExt [function]
sgs_Context* sgs_CreateEngineExt( sgs_MemFunc memfunc, void* mfuserdata )
returns a new scripting engine context, attached to the specified allocator
sgs_DestroyEngine [function]
sgs_DestroyEngine( sgs_Context* C )
destroys the passed context and frees all memory associated to it
sgs_ExecString [function alias]
SGSRESULT sgs_ExecString( sgs_Context* C, const char* str )
compiles and executes a string of text
- leaves the stack the same as it was before the call
- alias to
sgs_ExecBuffer( C, str, SGS_STRINGLENGTHFUNC( str ) )
- theoretically bytecode is supported but it will most probably be trimmed by the string length function, unless a different string termination mark is used, and a different string length function to detect it is set
error codes
- SGS_ECOMP: compiler error
- SGS_EINVAL: passed data was not recognized
sgs_ExecBuffer [function alias]
SGSRESULT sgs_ExecBuffer( sgs_Context* C, const char* buf, sgs_SizeVal size )
compiles and executes a buffer of text or bytecode
- leaves the stack the same as it was before the call
- alias to
sgs_EvalBuffer( C, buf, size, NULL )
error codes
- SGS_ECOMP: compiler error
- SGS_EINVAL: passed data was not recognized
sgs_EvalString [function alias]
SGSRESULT sgs_EvalString( sgs_Context* C, const char* str, int* rvc )
compiles and executes a string of text, optionally leaving the return values on stack and returning the number of values via rvc
- if
rvc
is not set (NULL), return values are removed - the stack is the same as it was before the call
- alias to sgs_EvalBuffer( C, str, SGS_STRINGLENGTHFUNC( str ), rvc )
error codes
- SGS_ECOMP: compiler error
- SGS_EINVAL: passed data was not recognized
sgs_EvalBuffer [function]
SGSRESULT sgs_EvalBuffer( sgs_Context* C, const char* buf, sgs_SizeVal size, int* rvc )
compiles and executes a buffer of text or bytecode, optionally leaving the return values on stack and returning the number of values via rvc
- if
rvc
is not set (NULL), return values are removed - the stack is the same as it was before the call
error codes
- SGS_ECOMP: compiler error
- SGS_EINVAL: passed data was not recognized
sgs_ExecFile [function alias]
SGSRESULT sgs_ExecFile( sgs_Context* C, const char* filename )
compiles and executes a file containing script text or bytecode
- leaves the stack the same as it was before the call
- alias to
sgs_EvalFile( C, filename, NULL )
error codes
- SGS_ECOMP: compiler error
- SGS_EINVAL: passed data was not recognized
sgs_EvalFile [function]
SGSRESULT sgs_EvalFile( sgs_Context* C, const char* filename, int* rvc )
compiles and executes a file containing script text or bytecode, optionally leaving the return values on stack and returning the number of values via rvc
- if
rvc
is not set (NULL), return values are removed - the stack is the same as it was before the call
error codes
- SGS_ECOMP: compiler error
- SGS_EINVAL: passed data was not recognized
sgs_Include [function alias]
SGSBOOL sgs_Include( sgs_Context* C, const char* name )
includes an item by the specified name, returning if completed successfully
- a C version of the
include
SGS function
- alias to
sgs_IncludeExt( C, name, NULL )
sgs_IncludeExt [function]
SGSBOOL sgs_IncludeExt( sgs_Context* C, const char* name, const char* searchpath )
includes an item by the specified name, optionally looking in the places specified by the search path, returning if completed successfully
- a C version of the include SGS function
searchpath
overrides SGS_PATH for the time of execution
sgs_Compile [function]
SGSRESULT sgs_Compile( sgs_Context* C, const char* buf, size_t size, char** outbuf, size_t* outsize )
compile a buffer of SGScript code, returning the compiled code buffer on success
- a C version of compile_sgs SGS function
outbuf
must be freed after usage with one of the relevant memory handling functions
outbuf
and outsize
will only contain valid buffer (pointer and size) on success
- all info/warning/error messages are passed to the Messaging system
error codes
- SGS_ECOMP: compiler error
- SGS_EINVAL: passed data was too big
- SGS_EINPROC: failed to serialize bytecode
sgs_DumpCompiled [function]
SGSRESULT sgs_DumpCompiled( sgs_Context* C, const char* buf, size_t size )
dump compiled bytecode or SGScript code buffer to stdout
- code is compiled before dumping if SGScript code is passed
- in that case, all info/warning/error messages are passed to the Messaging system
error codes
- SGS_ECOMP: compiler error
- SGS_EINVAL: passed data was too big
sgs_LoadLib_*** [functions]
SGSRESULT sgs_LoadLib_Fmt( sgs_Context* C )
SGSRESULT sgs_LoadLib_IO( sgs_Context* C )
SGSRESULT sgs_LoadLib_Math( sgs_Context* C )
SGSRESULT sgs_LoadLib_OS( sgs_Context* C )
SGSRESULT sgs_LoadLib_RE( sgs_Context* C )
SGSRESULT sgs_LoadLib_String( sgs_Context* C )
loads the library into the specified context
- it is generally unnecessary to check for these error codes
error codes
- SGS_E****: first error encountered (operation stopped somewhere in the middle)
sgs_Reg***Consts [function]
SGSRESULT sgs_RegFuncConsts( sgs_Context* C, const sgs_RegFuncConst* list, int size )
SGSRESULT sgs_RegIntConsts( sgs_Context* C, const sgs_RegIntConst* list, int size )
SGSRESULT sgs_RegRealConsts( sgs_Context* C, const sgs_RegRealConst* list, int size )
loads the specified list of constants in the context
- the end of list can be specified in two ways
- set the size to
sizeof(list)/sizeof(list[0])
- set the size to -1 and end the list with
SGS_RC_END()
- using both at the same time should be reserved to special cases only
error codes
- SGS_E****: first error encountered (operation stopped somewhere in the middle)
sgs_Init*** [functions]
void sgs_InitNull( sgs_Variable* out )
void sgs_InitBool( sgs_Variable* out, sgs_Bool value )
void sgs_InitInt( sgs_Variable* out, sgs_Int value )
void sgs_InitReal( sgs_Variable* out, sgs_Real value )
void sgs_InitStringBuf( sgs_Context* C, sgs_Variable* out, const char* str, sgs_SizeVal size )
void sgs_InitString( sgs_Context* C, sgs_Variable* out, const char* str )
void sgs_InitCFunction( sgs_Variable* out, sgs_CFunc func )
void sgs_InitObject( sgs_Context* C, sgs_Variable* out, void* data, sgs_ObjInterface* iface )
void* sgs_InitObjectIPA( sgs_Context* C, sgs_Variable* out, sgs_SizeVal added, sgs_ObjInterface* iface )
void sgs_InitPtr( sgs_Variable* out, void* ptr )
void sgs_InitObjectPtr( sgs_Variable* out, sgs_VarObj* obj )
- sgs_Bool is transformed to 0/1 before pushing, everything else is unchanged
- sgs_InitStringBuf( C, NULL, size ) would allocate an uninitialized buffer
- sgs_InitObjectIPA stands for "initialize object, allocate memory in-place"
- it means that the
added
memory space will be appended to the end of object allocation
- this allows to allocate all object data for most objects with just one allocation, instead of two
- the allocated memory will be returned and also available via sgs_GetObjectDataP
sgs_InitArray [function]
SGSRESULT sgs_InitArray( sgs_Context* C, sgs_Variable* out, sgs_SizeVal numitems )
creates an array at out
from numitems
last items on the stack, pops those items
error codes
- SGS_EINVAL: more items are selected than exist in the current stack frame
sgs_InitDict [function]
SGSRESULT sgs_InitDict( sgs_Context* C, sgs_Variable* out, sgs_SizeVal numitems )
creates a dict at out
from numitems
last items on the stack, pops those items
numitems
can be even or 0, since all odd arguments are keys and all even arguments are values
error codes
- SGS_EINVAL: more items are selected than exist in the current stack frame or
numitems
wasn't even or 0
sgs_InitMap [function]
SGSRESULT sgs_InitMap( sgs_Context* C, sgs_Variable* out, sgs_SizeVal numitems )
creates a map at out
from numitems
last items on the stack, pops those items
numitems
can be even or 0, since all odd arguments are keys and all even arguments are values
error codes
- SGS_EINVAL: more items are selected than exist in the current stack frame or
numitems
wasn't even or 0
sgs_Push*** [functions]
void sgs_PushNull( sgs_Context* C )
void sgs_PushBool( sgs_Context* C, sgs_Bool value )
void sgs_PushInt( sgs_Context* C, sgs_Int value )
void sgs_PushReal( sgs_Context* C, sgs_Real value )
void sgs_PushStringBuf( sgs_Context* C, const char* str, sgs_SizeVal size )
void sgs_PushString( sgs_Context* C, const char* str )
void sgs_PushCFunction( sgs_Context* C, sgs_CFunc func )
void sgs_PushObject( sgs_Context* C, void* data, sgs_ObjInterface* iface )
void* sgs_PushObjectIPA( sgs_Context* C, sgs_SizeVal added, sgs_ObjInterface* iface )
void sgs_PushPtr( sgs_Context* C, void* ptr )
void sgs_PushObjectPtr( sgs_Context* C, sgs_VarObj* obj )
SGSRESULT sgs_PushVariable( sgs_Context* C, sgs_Variable* var )
pushes the data on the stack, as a new entry, appended to the end
- sgs_Bool is transformed to 0/1 before pushing, everything else is unchanged
- sgs_PushStringBuf( C, NULL, size ) would allocate an uninitialized buffer
- sgs_PushObjectIPA stands for "push object, allocate memory in-place"
- it means that the
added
memory space will be appended to the end of object allocation
- this allows to allocate all object data for most objects with just one allocation, instead of two
- the allocated memory will be returned and also available via sgs_GetObjectData( C, -1 )
- sgs_PushVariable will increment the reference count of strings, SGS functions and objects
- it will also return EINVAL if type of variable isn't one of the allowed types
- these functions do not throw an error when the stack is full since there is no way to handle that
sgs_StoreVariable [function]
SGSRESULT sgs_StoreVariable( sgs_Context* C, sgs_Variable* var )
copy the topmost item of the current stack frame to the specified place, acquire it and pop it
error codes
- SGS_ENOTFND: stack frame is empty
sgs_Pop [function]
SGSRESULT sgs_Pop( sgs_Context* C, int count )
pops count
variables off the current frame of the stack
error codes
- SGS_EINVAL:
count
was bigger than the number of items in the current stack frame or count
is less than 0
sgs_PopSkip [function]
SGSRESULT sgs_PopSkip( sgs_Context* C, int count, int skip )
pops count
variables off the current frame of the stack, skipping the last skip
elements
error codes
- SGS_EINVAL:
count+skip
was bigger than the number of items in the current stack frame or count
is less than 0 or skip
is less than 0
sgs_InsertVariable [function]
SGSRESULT sgs_InsertVariable( sgs_Context* C, int pos, sgs_Variable* var )
inserts a variable var
at a given index pos
of the current stack frame, increasing its reference count
error codes
- SGS_EBOUNDS: index out of bounds
sgs_PushArray [function]
SGSRESULT sgs_PushArray( sgs_Context* C, sgs_SizeVal numitems )
creates an array from numitems
last items on the stack, pops those items and pushes the array
error codes
- SGS_EINVAL: more items are selected than exist in the current stack frame
sgs_PushDict [function]
SGSRESULT sgs_PushDict( sgs_Context* C, sgs_SizeVal numitems )
creates a dict from numitems
last items on the stack, pops those items and pushes the dict
numitems
can be even or 0, since all odd arguments are keys and all even arguments are values
error codes
- SGS_EINVAL: more items are selected than exist in the current stack frame or
numitems
wasn't even or 0
sgs_PushMap [function]
SGSRESULT sgs_PushMap( sgs_Context* C, sgs_SizeVal numitems )
creates a map from numitems
last items on the stack, pops those items and pushes the map
numitems
can be even or 0, since all odd arguments are keys and all even arguments are values
error codes
- SGS_EINVAL: more items are selected than exist in the current stack frame or
numitems
wasn't even or 0
sgs_PushItem [function]
SGSRESULT sgs_PushItem( sgs_Context* C, sgs_StkIdx item )
copy an item from the current stack frame and append it to the end of the stack
error codes
- SGS_EBOUNDS: index out of bounds
sgs_StoreItem [function]
SGSRESULT sgs_StoreItem( sgs_Context* C, sgs_StkIdx item )
copy last item in current stack frame to index item
and pop it
item
refers to a position after the pop operation, therefore -1 means one element before the last etc.
error codes
- SGS_EBOUNDS: index out of bounds
sgs_GetIndex*** [functions]
SGSRESULT sgs_GetIndexPPP( sgs_Context* C, sgs_Variable* obj, sgs_Variable* idx, sgs_Variable* out, int isprop )
SGSRESULT sgs_GetIndexIPP( sgs_Context* C, sgs_StkIdx obj, sgs_Variable* idx, sgs_Variable* out, int isprop )
SGSRESULT sgs_GetIndexPIP( sgs_Context* C, sgs_Variable* obj, sgs_StkIdx idx, sgs_Variable* out, int isprop )
SGSRESULT sgs_GetIndexIIP( sgs_Context* C, sgs_StkIdx obj, sgs_StkIdx idx, sgs_Variable* out, int isprop )
SGSRESULT sgs_GetIndexPPI( sgs_Context* C, sgs_Variable* obj, sgs_Variable* idx, sgs_StkIdx out, int isprop )
SGSRESULT sgs_GetIndexIPI( sgs_Context* C, sgs_StkIdx obj, sgs_Variable* idx, sgs_StkIdx out, int isprop )
SGSRESULT sgs_GetIndexPII( sgs_Context* C, sgs_Variable* obj, sgs_StkIdx idx, sgs_StkIdx out, int isprop )
SGSRESULT sgs_GetIndexIII( sgs_Context* C, sgs_StkIdx obj, sgs_StkIdx idx, sgs_StkIdx out, int isprop )
retrieve index/property idx
from the specified variable obj
to the position out
, specifying retrieval type via isprop
- last 3 letters in function name determines the type for parameters 2, 3 and 4: P for pointers, I for stack indices
error codes
- SGS_EBOUNDS: something was not pointing inside the current stack frame
- SGS_ENOTFND: index/property was not found
- other codes may appear if returned by custom objects
sgs_SetIndex*** [functions]
SGSRESULT sgs_SetIndexPPP( sgs_Context* C, sgs_Variable* obj, sgs_Variable* idx, sgs_Variable* val, int isprop )
SGSRESULT sgs_SetIndexIPP( sgs_Context* C, sgs_StkIdx obj, sgs_Variable* idx, sgs_Variable* val, int isprop )
SGSRESULT sgs_SetIndexPIP( sgs_Context* C, sgs_Variable* obj, sgs_StkIdx idx, sgs_Variable* val, int isprop )
SGSRESULT sgs_SetIndexIIP( sgs_Context* C, sgs_StkIdx obj, sgs_StkIdx idx, sgs_Variable* val, int isprop )
SGSRESULT sgs_SetIndexPPI( sgs_Context* C, sgs_Variable* obj, sgs_Variable* idx, sgs_StkIdx val, int isprop )
SGSRESULT sgs_SetIndexIPI( sgs_Context* C, sgs_StkIdx obj, sgs_Variable* idx, sgs_StkIdx val, int isprop )
SGSRESULT sgs_SetIndexPII( sgs_Context* C, sgs_Variable* obj, sgs_StkIdx idx, sgs_StkIdx val, int isprop )
SGSRESULT sgs_SetIndexIII( sgs_Context* C, sgs_StkIdx obj, sgs_StkIdx idx, sgs_StkIdx val, int isprop )
set index/property idx
in the specified variable obj
to the value val
, specifying type via isprop
- last 3 letters in function name determines the type for parameters 2, 3 and 4: P for pointers, I for stack indices
error codes
- SGS_EBOUNDS: something was not pointing inside the current stack frame
- SGS_ENOTFND: index/property was not found
- SGS_EINVAL: specified value could not be used
- other codes may appear if returned by custom objects
sgs_PushIndex** [functions]
SGSRESULT sgs_PushIndexPP( sgs_Context* C, sgs_Variable* obj, sgs_Variable* idx, int isprop )
SGSRESULT sgs_PushIndexIP( sgs_Context* C, sgs_StkIdx obj, sgs_Variable* idx, int isprop )
SGSRESULT sgs_PushIndexPI( sgs_Context* C, sgs_Variable* obj, sgs_StkIdx idx, int isprop )
SGSRESULT sgs_PushIndexII( sgs_Context* C, sgs_StkIdx obj, sgs_StkIdx idx, int isprop )
retrieve and push index/property idx
from the specified variable obj
, specifying retrieval type via isprop
- last 2 letters in function name determines the type for parameters 2 and 3: P for pointers, I for stack indices
error codes
- SGS_EBOUNDS: something was not pointing inside the current stack frame
- SGS_ENOTFND: index/property was not found
- other codes may appear if returned by custom objects
sgs_StoreIndex** [functions]
SGSRESULT sgs_StoreIndexPP( sgs_Context* C, sgs_Variable* obj, sgs_Variable* idx, int isprop )
SGSRESULT sgs_StoreIndexIP( sgs_Context* C, sgs_StkIdx obj, sgs_Variable* idx, int isprop )
SGSRESULT sgs_StoreIndexPI( sgs_Context* C, sgs_Variable* obj, sgs_StkIdx idx, int isprop )
SGSRESULT sgs_StoreIndexII( sgs_Context* C, sgs_StkIdx obj, sgs_StkIdx idx, int isprop )
set index/property idx
in the specified variable obj
to the topmost variable in stack, specifying type via isprop
, then pop the topmost variable in stack if successful
- last 2 letters in function name determines the type for parameters 2 and 3: P for pointers, I for stack indices
error codes
- SGS_EBOUNDS: something was not pointing inside the current stack frame
- SGS_ENOTFND: index/property was not found
- SGS_EINVAL: specified value could not be used
- SGS_EINPROC: current stack frame is empty
- other codes may appear if returned by custom objects
sgs_GetGlobalPP [function]
SGSRESULT sgs_GetGlobalPP( SGS_CTX, sgs_Variable* idx, sgs_Variable* out )
retrieve a global variable by index idx
to position out
error codes
- SGS_ENOTSUP:
idx
was not a string
- SGS_ENOTFND: index was not found
sgs_SetGlobalPP [function]
SGSRESULT sgs_SetGlobalPP( SGS_CTX, sgs_Variable* idx, sgs_Variable* val )
set a global variable val
to index idx
error codes
- SGS_ENOTSUP:
idx
was not a string / idx
was _G and val
was not a dict
sgs_PushProperty [function]
SGSRESULT sgs_PushProperty( sgs_Context* C, sgs_StkIdx obj, const char* name )
load and push the property of the item obj
in the current stack frame
error codes
- SGS_EBOUNDS:
obj
was not pointing inside the current stack frame
- SGS_EINPROC: current stack frame is empty
- SGS_ENOTFND: property was not found
- other codes may appear if returned by custom objects
sgs_StoreProperty [function]
SGSRESULT sgs_StoreProperty( sgs_Context* C, sgs_StkIdx obj, const char* name )
copy and pop the topmost item of the current stack frame to the property name
of variable obj
error codes
- SGS_EBOUNDS:
obj
was not pointing inside the current stack frame
- SGS_ENOTFND: property was not found
- other codes may appear if returned by custom objects
sgs_PushNumIndex [function]
SGSRESULT sgs_PushNumIndex( sgs_Context* C, sgs_StkIdx obj, sgs_Int idx )
load and push the integer index idx
of the variable obj
error codes:
- SGS_EBOUNDS:
obj
was not pointing inside the current stack frame / array index out of bounds
- SGS_ENOTFND: index was not found
- other codes may appear if returned by custom objects
sgs_StoreNumIndex [function]
SGSRESULT sgs_StoreNumIndex( sgs_Context* C, sgs_StkIdx obj, sgs_Int idx )
copy and pop the topmost item of the current stack to the integer index idx
of variable obj
error codes
- SGS_EBOUNDS:
obj
was not pointing inside the current stack frame / array index out of bounds
- SGS_ENOTFND: index was not found
- other codes may appear if returned by custom objects
sgs_PushGlobal [function]
SGSRESULT sgs_PushGlobal( sgs_Context* C, const char* name )
push the global variable name
on the stack
error codes
- SGS_ENOTFND: variable was not found
sgs_StoreGlobal [function]
SGSRESULT sgs_StoreGlobal( sgs_Context* C, const char* name )
copy and pop the topmost stack item to the global variable name
- _G is the environment table (a superglobal, list of global variable names and values)
error codes
- SGS_EINPROC: current stack frame was empty
- SGS_ENOTSUP: variable was not a dict (_G only accepts dict values)
sgs_GetEnv [function]
void sgs_GetEnv( SGS_CTX, sgs_Variable* out )
retrieve the global environment dict variable (_G)
sgs_SetEnv [function]
SGSRESULT sgs_SetEnv( SGS_CTX, sgs_Variable* var )
set a global environment dict variable from the variable var
error codes
- SGS_ENOTSUP: variable was not a dict (_G only accepts dict values)
sgs_PushEnv [function]
void sgs_PushEnv( SGS_CTX )
retrieve and push the global environment dict variable (_G)
sgs_StoreEnv [function]
SGSRESULT sgs_StoreEnv( SGS_CTX )
set a global environment dict variable from the topmost stack item, then pop it if successful
error codes
- SGS_EINPROC: current stack frame was empty
- SGS_ENOTSUP: variable was not a dict (_G only accepts dict values)
sgs_PushPath [function]
SGSRESULT sgs_PushPath( sgs_Context* C, sgs_StkIdx item, const char* path, ... )
push the variable specified by starting point item
and traversal path path
The safety of this function is similar to that of the printf family of functions. Be explicit in what types you pass to the variable argument list to avoid errors.
- the syntax of
path
:
- a list of letters, specifying a sub-variable to request (o,p,s,i,k,n)
table of accepted letters
letter | property? | variable arguments | virtual machine access mode / description |
o | yes | SizeVal | integer property |
p | yes | C string | string property |
s | yes | SizeVal, buffer | special string property |
i | no | SizeVal | integer index |
k | no | C string | string index |
n | no | SizeVal, buffer | special string index |
- legend:
- SizeVal: sgs_SizeVal / int32_t
- C string: null-terminated char* string
- buffer: char* byte array, size is specified in the previous argument
- property?: if yes, property access is used (object.property), otherwise index access is used (object[index])
error codes
- SGS_EINVAL: invalid symbol found in path / corresponding variable arguments had an invalid value
- other errors, as returned by sgs_PushIndex***()
sgs_StorePath [function]
SGSRESULT sgs_StorePath( sgs_Context* C, sgs_StkIdx item, const char* path, ... )
copy and pop the topmost item on stack to variable specified by starting point item
and traversal path path
The safety of this function is similar to that of the printf family of functions. Be explicit in what types you pass to the variable argument list to avoid errors.
- the syntax of
path
is the same as with sgs_PushPath
- the last item on the path (or in the case of an empty path, the starting point) is accessed with a store operation, the rest - with a push operation
error codes
- SGS_EINVAL: invalid symbol found in path / corresponding variable arguments had an invalid value
- SGS_EINPROC: current stack frame is empty
- other errors, as returned by sgs_PushIndex*** or sgs_StoreIndex***
sgs_ArgErrorExt [function]
int sgs_ArgErrorExt( sgs_Context* C, int argid, int method, const char* expect, const char* expfx )
prints the argument type mismatch error
expfx
- prefix of expect
, put exactly before this for things like 'strict '
- always returns 0 so it can be used to return and print an error in the same statement
sgs_ArgError [function]
int sgs_ArgError( sgs_Context* C, int argid, int expect, int is_strict )
prints the argument type mismatch error
- always returns 0 so it can be used to return and print an error in the same statement
sgs_***ArgError [function aliases]
int sgs_FuncArgError( sgs_Context* C, int argid, int expect, int is_strict )
int sgs_MethodArgError( sgs_Context* C, int argid, int expect, int is_strict )
prints the argument type mismatch error
- always returns 0 so it can be used to return and print an error in the same statement
- alias to
sgs_ArgError( C, argid, Func/Method => 0/1, expect, is_strict )
sgs_LoadArgsExt(VA) [function]
SGSMIXED sgs_LoadArgsExt( sgs_Context* C, int from, const char* cmd, ... )
SGSMIXED sgs_LoadArgsExtVA( sgs_Context* C, int from, const char* cmd, va_list* args )
parse the stack items and retrieve their data according to cmd
, starting from item from
- for anything function requires, pass the value; for anything it returns - the pointer to the value
cmd
is a string consisting of one-character commands
- the commands are grouped into two kinds: control commands and parsing commands
- function returns whether all required arguments have been parsed successfully
- thus, if function returns < 1, state of outputs is somewhat unknown unless filled with defaults
- it is guaranteed that all arguments will be parsed from first (specified) forward, not in any other way
null
values in optional arguments are skipped (this may not apply to custom checking functions)
unlike sgs_LoadArgs, it returns SGSMIXED
and must be checked differently ("ret.val. > 0", if same output needed)
control commands
?
-- only check, do not write the result and do not require a pointer to write the data to
!
-- enable strict parsing for the next item (requires exactly the type specified
-
,+
-- enable (-) or disable (+) treating integers as signed (default = true)
|
-- mark the point where required arguments end and optional arguments begin
#
-- do range checking on integer arguments (min/max of the required types)
^
-- clamp the argument to the range of the required type
~
-- ignore ranges and chop out-of-range integers (default)
<
-- move argument pointer 1 item back (cannot move it before 0)
>
-- move argument pointer 1 item forward
@
-- specify that this is a method (argument 0 = 'this'; shifts argument indices on error printing by -1)
.
-- specify the end of argument list (how many arguments are expected)
parsing commands
n
-- check for null
(returns SGSBOOL = 1, always strict)
b
-- check for bool
(returns sgs_Bool)
c
-- check for int
(returns int8_t or uint8_t, depending on sign settings, may check ranges)
w
-- check for int
(returns int16_t or uint16_t, depending on sign settings, may check ranges)
l
-- check for int
(returns int32_t or uint32_t, depending on sign settings, may check ranges)
q
-- check for int
(returns int64_t or uint64_t, depending on sign settings, may check ranges)
i
-- check for int
(returns sgs_Int, may check ranges)
f
-- check for real
(returns float)
d
-- check for real
(returns double)
r
-- check for real
(returns sgs_Real)
s
-- check for string
(returns char*)
m
-- check for string
(returns char* string and sgs_SizeVal size)
p
-- check for func/cfunc/object with CALL
(callables) (returns SGSBOOL = 1)
a
-- check for array
(returns sgs_SizeVal size, use -1 as starting value to check optional arguments)
t
-- check for dict
(returns sgs_SizeVal size, use -1 as starting value to check optional arguments)
h
-- check for map
(returns sgs_SizeVal size, use -1 as starting value to check optional arguments)
o
-- check for object
(requires void** interface, returns <type>* data - the data pointer)
&
-- check for pointer
(returns void* data - the pointer)
v
-- check for any (non-null if strict, returns sgs_Variable data)
x
-- call a custom checking function (requires sgs_ArgCheckFunc, everything else depends on function)
error codes
- SGS_EINVAL: error in
cmd
(wrong character/argument pointer moved before 0)
sgs_LoadArgs [function alias]
SGSBOOL sgs_LoadArgs( sgs_Context* C, const char* cmd, ... )
parse the stack items and retrieve their data according to cmd
, starting from item 0
unlike sgs_LoadArgsExt(VA), it returns bool
- whether all required arguments have been successfully parsed
- for more info on syntax and usage, refer to sgs_LoadArgsExt(VA)
- alias to
sgs_LoadArgsExt( C, 0, cmd, ... )>0
sgs_ParseMethod [function]
SGS_PARSE_METHOD [function alias]
sgs_Method [function]
SGSBOOL sgs_Method( sgs_Context* C )
unlock the 'this' variable, return if the function was called as a method (and thus variable was unlocked)
- method calls look like this: "object.method(...)"
sgs_(Force)HideThis [functions]
SGSBOOL sgs_HideThis( sgs_Context* C )
SGSBOOL sgs_ForceHideThis( sgs_Context* C )
hide the 'this' variable, return if successful
- sgs_ForceHideThis attempts to hide the first item on stack even if it didn't belong to the call, sgs_HideThis only does it if it belongs to the call and was hidden before
- the hiding method is stack offset pointer shift
sgs_FCall(P) [functions]
SGSRESULT sgs_FCall( sgs_Context* C, int args, int expect, int gotthis )
call the topmost variable on stack with the arguments before it, returning the expected number of variables on stack
SGSRESULT sgs_FCallP( sgs_Context* C, sgs_Variable* var, int args, int expect, int gotthis )
call the variable with the arguments on stack, returning the expected number of variables on stack
var
: the callable variable to call as a function
args
: the primary variables to be passed to the function, in the same order they are in the stack
expect
: the number of variables to be left after a successful call
gotthis
: whether the function is a method and an additional argument needs to be passed as the 'this' value before others
After a successful call, all arguments and the function will be popped off the stack and the expected number of variables will appear in their place. If the underlying callable does not return enough arguments, 'null' variables will be pushed instead. If the number of returned values is bigger than expected, only the first expected return values will stay on the stack.
- expected stack structure:
- (if gotthis != 0) [this]
- [argument] x
args
- [callable]
- a callable is one of the following:
- SGS function
- C function
- object with CALL interface function defined
Stack is returned to the expected state only if the return value implies success (>= 0) or is equal to SGS_EINPROC. Otherwise, it's left exactly as it was before the call.
The return value 1
is returned if function call was aborted.
error codes
- SGS_EINPROC: topmost item on stack was not callable
- SGS_EINVAL: not enough values in current stack frame (must have at least
args + (gotthis?1:0) + (is_sgs_FCallP?0:1)
)
sgs_(This)Call(P) [function aliases]
SGSRESULT sgs_Call( sgs_Context* C, int args, int expect )
SGSRESULT sgs_ThisCall( sgs_Context* C, int args, int expect )
call the topmost variable on stack with the arguments before it, returning the expected number of variables on stack
SGSRESULT sgs_Call( sgs_Context* C, sgs_Variable* var, int args, int expect )
SGSRESULT sgs_ThisCall( sgs_Context* C, sgs_Variable* var, int args, int expect )
call the variable with the arguments on stack, returning the expected number of variables on stack
- aliases to sgs_FCall(P), for the first function of each group
gotthis = 0
, for the second gotthis = 1
.
sgs_GlobalCall [function]
SGSRESULT sgs_GlobalCall( sgs_Context* C, const char* name, int args, int expect )
call the global variable name
as a function
error codes
- SGS_ENOTFND: global variable was not found
- SGS_EINPROC: item found was not callable
- SGS_EINVAL: not enough values in current stack frame (must have at least
args + (gotthis?1:0)
)
sgs_TypeOf [function]
SGSRESULT sgs_TypeOf( sgs_Context* C )
return the type name string of topmost variable in current stack frame
- if the object does not support the specific part of the conversion interface function, a string of format "object (%p)" is returned to ensure expected type name comparison capabilities
error codes
- SGS_EINPROC: current stack frame was empty
sgs_DumpVar [function]
SGSRESULT sgs_DumpVar( sgs_Context* C, int maxdepth )
convert the topmost variable of current stack frame to a highly informative string that should display the contents of the variable, up to maxdepth
depth
- if object does not have the DUMP interface function implemented, only its pointer in memory and reference count are displayed
error codes
- SGS_EINPROC: current stack frame was empty
- SGS_EINVAL: invalid base variable type found in variable (not really expected to happen unless custom variable creation is done)
sgs_GCExecute [function]
SGSRESULT sgs_GCExecute( sgs_Context* C )
call the garbage collector on the VM
- this procedure may take some time if the object graph is big
- during the procedure, the GCMARK interface functions of objects are invoked for the objects visible from entry points (like stack and global table)
- aborting the procedure via error codes could lead the system into an unrecoverable state
error codes
- any code can be returned by GCMARK and DESTRUCT functions, doing so would abort the process if the code is not either SGS_SUCCESS or SGS_ENOTFND
sgs_PadString [function]
SGSRESULT sgs_PadString( sgs_Context* C )
replace the topmost variable of current stack frame with a string variable where two spaces are appended after every newline
error codes
- SGS_EINPROC: current stack frame is empty or output string size exceeds limit
- SGS_EINVAL: topmost variable is not a string
sgs_ToPrintSafeString [function]
SGSRESULT sgs_ToPrintSafeString( sgs_Context* C )
replace the topmost variable of current stack frame with a string where all non-printable (except space), non-ASCII characters converted to a character hex code
error codes
- SGS_EINPROC: current stack frame is empty or output string size exceeds limit
sgs_StringConcat [function]
SGSRESULT sgs_StringConcat( sgs_Context* C, int args )
concatenate the args
number of topmost string variables in the current stack frame
error codes
- SGS_EINVAL: not enough (less than
args
) variables were found in the current stack frame
sgs_ClPushNulls [function]
SGSRESULT sgs_ClPushNulls( sgs_Context* C, sgs_StkIdx num )
push num
empty closures to the closure stack
error codes
- SGS_EINVAL:
num
was less than 0
sgs_ClPushItem [function]
SGSRESULT sgs_ClPushItem( sgs_Context* C, sgs_StkIdx item )
push a variable item
on stack as a closure to the closure stack
error codes
- SGS_EBOUNDS: index out of bounds
sgs_ClPop [function]
SGSRESULT sgs_ClPop( sgs_Context* C, sgs_StkIdx num )
pop num
closures from the closure stack
error codes
- SGS_EINPROC: attempted to pop more closures than there are on the stack
sgs_MakeClosure [function]
SGSRESULT sgs_MakeClosure( sgs_Context* C, sgs_Variable* func, sgs_StkIdx clcount, sgs_Variable* out )
make a callable closure object from the specified callable func
and clcount
closures on stack, return it at position out
error codes
- SGS_EINPROC: attempted to use more closures than there are on the stack
sgs_ClGetItem [function]
SGSRESULT sgs_ClGetItem( sgs_Context* C, sgs_StkIdx item, sgs_Variable* out )
retrieve the variable from a closure item
on stack
error codes
- SGS_EBOUNDS: index out of bounds
sgs_ClSetItem [function]
SGSRESULT sgs_ClSetItem( sgs_Context* C, sgs_StkIdx item, sgs_Variable* var )
set the variable var
to a closure item
on stack
error codes
- SGS_EBOUNDS: index out of bounds
sgs_CloneItem [function]
SGSRESULT sgs_CloneItem( sgs_Context* C, sgs_StkIdx item )
push a copy of the specified stack item
Even though operations with functions and strings succeed, functions and strings are not actually cloned since they are immutable.
error codes
- SGS_EBOUNDS: stack item index was out of bounds
- SGS_ENOTFND: the object does not support cloning
sgs_ObjectAction [function]
SGSMIXED sgs_ObjectAction( sgs_Context* C, sgs_StkIdx item, int action, int arg )
execute an action on the specified stack item
actions
- SGS_ACT_ARRAY_PUSH
- append the last
arg
items on stack to the array
- error codes
- SGS_EINVAL:
item
was not an array, arg
was negative or bigger than stack frame
- SGS_ACT_ARRAY_POP
- remove the last
arg
items from the end of the array
- error codes
- SGS_EINVAL:
item
was not an array, arg
was negative or bigger than size of array
- SGS_ACT_ARRAY_POPRET
- remove the last
arg
items from the end of the array and return them in the order they were stored (last items on array are last on stack)
- error codes
- SGS_EINVAL:
item
was not an array, arg
was negative or bigger than size of array
- SGS_ACT_ARRAY_FIND
- find and return the index of variable specified in
arg
- error codes
- SGS_EINVAL:
item
was not an array
- SGS_EBOUNDS:
arg
was out of bounds
- SGS_ENOTFND:
arg
was not found inside item
- SGS_ACT_ARRAY_RM_ONE
- find and remove only the first copy of variable specified in
arg
, return if found and removed
- error codes
- SGS_EINVAL:
item
was not an array
- SGS_EBOUNDS:
arg
was out of bounds
- SGS_ACT_ARRAY_RM_ALL
- find and remove all copies of variable specified in
arg
, return how many were found and removed
- error codes
- SGS_EINVAL:
item
was not an array
- SGS_EBOUNDS:
arg
was out of bounds
- SGS_ACT_DICT_UNSET
- unset a key-value pair from a dict
- error codes
- SGS_EINVAL:
item
was not a dict, arg
was not pointing to a stack item of string
type
- SGS_ACT_MAP_UNSET
- unset a key-value pair from a map
- error codes
- SGS_EINVAL:
item
was not a map, arg
was out of bounds
error codes
- SGS_E****: action-specific
- SGS_ENOTFND: action was not found
sgs_Serialize [function]
SGSRESULT sgs_Serialize( sgs_Context* C )
serialize the topmost variable of the current stack frame (convert to a binary recreation instruction stream)
- the following variable types can be serialized:
- null, bool, int, real, string, func (SGS function)
- objects with the SERIALIZE interface function defined
- serialized data has the following format:
- a list of 'P' or 'C' commands
- 'P' (push) command: byte - variable type; variable data
- variable data: nothing for null, byte for bool, int64 for int, double for real, int32 + char[] for string
- 'C' (call) command: int32 - number of arguments; byte - function name size; char[] - function name
error codes
- SGS_EBOUNDS: current stack frame was empty
- SGS_EINVAL: an unserializable topmost variable was found (function)
- SGS_EINPROC: unknown memory error
sgs_SerializeObject [function]
SGSRESULT sgs_SerializeObject( sgs_Context* C, int args, const char* func )
write the serialized code for an object's unserializing function
error codes
- SGS_EINVAL: function name was too long (255 characters or more)
- SGS_EINPROC: function was used outside serialization interface function
sgs_Unserialize [function]
SGSRESULT sgs_Unserialize( sgs_Context* C )
unserialize the topmost string variable of the current stack frame (run the binary recreation instruction stream)
Be mindful of the data sources you use - calls to any global function can be placed in the instruction stream.
sgs_Assign [function]
void sgs_Assign( sgs_Context* C, sgs_Variable* var_to, sgs_Variable* var_from )
release var_to
, copy var_from
to var_to
, acquire the new value
sgs_ArithOp [function]
SGSRESULT sgs_ArithOp( sgs_Context* C, sgs_Variable* out, sgs_Variable* A, sgs_Variable* B, int op )
perform the specified operation on variables A and B, returning the value on out
this function prints errors, exactly like VM would (internally there are the same functions)
- this function can perform 5 operations, which are specified by passing the following values to
op
:
- SGS_EOP_ADD: +
- SGS_EOP_SUB: - (binary)
- SGS_EOP_MUL: *
- SGS_EOP_DIV: /
- SGS_EOP_MOD: %
- SGS_EOP_NEGATE: - (unary, uses only
A
)
error codes
- SGS_ENOTSUP: operation not supported (invalid operation ID)
- SGS_EINVAL: specified arithmetic operation is not supported by the given set of arguments
- SGS_EINPROC: division by 0
sgs_IncDec [function]
SGSRESULT sgs_IncDec( SGS_CTX, sgs_Variable* out, sgs_Variable* A, int inc )
increment or decrement the specified variable A
to the output out
this function prints errors, exactly like VM would (internally there are the same functions)
- if inc is non-zero, variable is incremented; otherwise it is decremented
error codes
- SGS_EINVAL: variable was not int or real
sgs_Compare [function]
int sgs_Compare( sgs_Context* C, sgs_Variable* v1, sgs_Variable* v2 )
return the difference between variables, as int -1/0/1
sgs_EqualTypes [function]
SGSBOOL sgs_EqualTypes( sgs_Variable* v1, sgs_Variable* v2 )
return if types of both variables are exactly equal
- both type variables and interface pointers (only if both variables are objects) are checked for equality
sgs_Get*** [functions]
sgs_Bool sgs_GetBool( sgs_Context* C, sgs_StkIdx item )
sgs_Int sgs_GetInt( sgs_Context* C, sgs_StkIdx item )
sgs_Real sgs_GetReal( sgs_Context* C, sgs_StkIdx item )
void* sgs_GetPtr( sgs_Context* C, sgs_StkIdx item )
return an item from the current stack frame, converted to the specified type
sgs_Bool sgs_GetBoolP( sgs_Context* C, sgs_Variable* var )
sgs_Int sgs_GetIntP( sgs_Context* C, sgs_Variable* var )
sgs_Real sgs_GetRealP( sgs_Context* C, sgs_Variable* var )
void* sgs_GetPtrP( sgs_Context* C, sgs_Variable* var )
return the value of the specified variable, converted to the specified type
- if
item
is out of bounds, 0 is returned
sgs_To*** [functions]
sgs_Bool sgs_ToBool( sgs_Context* C, sgs_StkIdx item )
sgs_Int sgs_ToInt( sgs_Context* C, sgs_StkIdx item )
sgs_Real sgs_ToReal( sgs_Context* C, sgs_StkIdx item )
void* sgs_ToPtr( sgs_Context* C, sgs_StkIdx item )
return an item from the current stack frame, converted in-place to the specified type
sgs_Bool sgs_ToBoolP( sgs_Context* C, sgs_Variable* var )
sgs_Int sgs_ToIntP( sgs_Context* C, sgs_Variable* var )
sgs_Real sgs_ToRealP( sgs_Context* C, sgs_Variable* var )
void* sgs_GetPtrP( sgs_Context* C, sgs_Variable* var )
return the value of the specified variable, converted in-place to the specified type
- in ***P functions previous variable is properly released before conversion takes place and reacquired afterwards
- in-place conversion means that if the function succeeds, the variable will have the requested type
sgs_ToStringBuf(Fast)(P) [functions]
char* sgs_ToStringBuf( sgs_Context* C, sgs_StkIdx item, sgs_SizeVal* outsize )
char* sgs_ToStringBufFast( sgs_Context* C, sgs_StkIdx item, sgs_SizeVal* outsize )
return an item from the current stack frame, converted in-place to string
char* sgs_ToStringBufP( sgs_Context* C, sgs_Variable* var, sgs_SizeVal* outsize )
char* sgs_ToStringBufFastP( sgs_Context* C, sgs_Variable* var, sgs_SizeVal* outsize )
return the value of the specified variable, converted in-place to string
- in ***P functions previous variable is properly released before conversion takes place and reacquired afterwards
- if
item
is out of bounds or conversion fails, NULL is returned
- the 'fast' version uses type name conversion on object, instead of string conversion - this is to avoid recursion while generating a short description about object contents
- length of string is returned to the value that
outsize
points to
sgs_ToString(Fast)(P) [function aliases]
char* sgs_ToString( sgs_Context* C, sgs_StkIdx item )
char* sgs_ToStringFast( sgs_Context* C, sgs_StkIdx item )
return an item from the current stack frame, converted in-place to string
char* sgs_ToStringP( sgs_Context* C, sgs_Variable* var )
char* sgs_ToStringFastP( sgs_Context* C, sgs_Variable* var )
return the value of the specified variable, converted in-place to string
- in ***P functions previous variable is properly released before conversion takes place and reacquired afterwards
- these are aliases of sgs_ToStringBuf(Fast)(P) with the third argument set to NULL
sgs_RegisterType [function]
SGSRESULT sgs_RegisterType( sgs_Context* C, const char* name, sgs_ObjInterface* iface )
register a type interface by mapping it to a name
error codes
- SGS_EINVAL: iface was NULL
- SGS_EINPROC: the name is already used
sgs_UnregisterType [function]
SGSRESULT sgs_UnregisterType( sgs_Context* C, const char* name )
unregister a type interface by its name
error codes
- SGS_ENOTFND: the specified type name was not mapped to any interface
sgs_FindType [function]
sgs_ObjInterface* sgs_FindType( sgs_Context* C, const char* name )
finds the type interface that is mapped to the specified name or returns NULL if that type name cannot be found
sgs_IsObject(P) [functions]
SGSBOOL sgs_IsObject( sgs_Context* C, sgs_StkIdx item, sgs_ObjInterface* iface )
returns whether the specified stack item item
is an object with the interface pointer iface
- if
item
is out of bounds or not an object or doesn't have the specified interface, 0 is returned
SGSBOOL sgs_IsObjectP( sgs_Context* C, sgs_Variable* var, sgs_ObjInterface* iface )
returns whether the specified variable var
is an object with the interface pointer iface
sgs_IsType(P) [function aliases]
SGSBOOL sgs_IsType( sgs_Context* C, sgs_StkIdx item, const char* type )
returns whether the specified stack item item
is an object of the specified type
- alias of
sgs_IsObject( C, item, sgs_FindType( C, type ) )
SGSBOOL sgs_IsTypeP( sgs_Context* C, sgs_Variable* var, const char* type )
returns whether the specified variable var
is an object of the specified type
- alias of
sgs_IsObjectP( C, var, sgs_FindType( C, type ) )
sgs_IsCallable(P) [functions]
SGSBOOL sgs_IsCallable( sgs_Context* C, sgs_StkIdx item )
returns whether the specified stack item item
is callable
- if
item
is out of bounds, 0 is returned
SGSBOOL sgs_IsCallableP( sgs_Context* C, sgs_Variable* var )
returns whether the specified variable var
is callable
- callable variables are either SGS functions or C functions or objects with the CALL interface implemented
sgs_IsNumericString [function]
SGSBOOL sgs_IsNumericString( const char* str, sgs_SizeVal size )
checks if the string is convertible to an integer/real
- more info at @<Numeric string parsing rules>
sgs_Parse*** [functions]
SGSBOOL sgs_ParseBool( sgs_Context* C, sgs_StkIdx item, sgs_Bool* out )
SGSBOOL sgs_ParseInt( sgs_Context* C, sgs_StkIdx item, sgs_Int* out )
SGSBOOL sgs_ParseReal( sgs_Context* C, sgs_StkIdx item, sgs_Real* out )
SGSBOOL sgs_ParseString( sgs_Context* C, sgs_StkIdx item, char** out, sgs_SizeVal* size )
SGSBOOL sgs_ParseObjectPtr( sgs_Context* C, sgs_StkIdx item, sgs_ObjInterface* iface, sgs_VarObj** out, int strict )
SGSBOOL sgs_ParsePtr( sgs_Context* C, sgs_StkIdx item, void** out )
attempts to parse the specified item of the current stack frame, returning whether parsing was successful
SGSBOOL sgs_ParseBoolP( sgs_Context* C, sgs_Variable* var, sgs_Bool* out )
SGSBOOL sgs_ParseIntP( sgs_Context* C, sgs_Variable* var, sgs_Int* out )
SGSBOOL sgs_ParseRealP( sgs_Context* C, sgs_Variable* var, sgs_Real* out )
SGSBOOL sgs_ParseStringP( sgs_Context* C, sgs_Variable* var, char** out, sgs_SizeVal* size )
SGSBOOL sgs_ParseObjectPtrP( sgs_Context* C, sgs_Variable* var, sgs_ObjInterface* iface, sgs_VarObj** out, int strict )
SGSBOOL sgs_ParsePtrP( sgs_Context* C, sgs_Variable* var, void** out )
attempts to parse the specified varuabke, returning whether parsing was successful
- the parsing rules:
- for
sgs_ParsePtr
/sgs_ParsePtrP
, unlike every other parsing function, only null/ptr types are considered valid
- for
sgs_ParseObjectPtr
/sgs_ParseObjectPtrP
, only objects with the specified interface iface
are valid unless strict = 0, then null
is valid too
- if
item
is out of bounds, fail
- if item has the type
null
, func
or cfunc
, fail
- if item is of
string
type and bool
is requested, fail
- if item is of
string
type and int
/real
is requested, try to convert
- everything else succeeds
sgs_Global*** [functions]
sgs_Bool sgs_GlobalBool( SGS_CTX, const char* name )
sgs_Int sgs_GlobalInt( SGS_CTX, const char* name )
sgs_Real sgs_GlobalReal( SGS_CTX, const char* name )
char* sgs_GlobalStringBuf( SGS_CTX, const char* name, sgs_SizeVal* outsize )
char* sgs_GlobalString( SGS_CTX, const char* name )
retrieve a global variable, converted to the specified type
sgs_GlobalString[Buf] pushes the variable on the stack to be able to reliably return the string pointer
- if variable is not found, 0 / NULL is returned
- if string cannot be parsed (variable is null or a function), NULL is returned
- this is done because converting these values does not yield useful results with global variables
sgs_PushIterator(P) [functions]
SGSRESULT sgs_PushIterator( sgs_Context* C, sgs_StkIdx item )
create and push an iterator from the specified item of the current stack frame
SGSRESULT sgs_PushIteratorP( sgs_Context* C, sgs_Variable* var )
create and push an iterator from the specified variable
error codes
- SGS_EBOUNDS: index out of bounds
- SGS_ENOTSUP: variable type does not support iterators (only objects support them)
- SGS_ENOTFND: object type does not support iterators (iterator conversion request failed)
- any other code can be returned by the object
sgs_GetIterator(P) [functions]
SGSRESULT sgs_GetIterator( sgs_Context* C, sgs_StkIdx item, sgs_Variable* out )
create an iterator from the specified item of the current stack frame
SGSRESULT sgs_GetIteratorP( sgs_Context* C, sgs_Variable* var, sgs_Variable* out )
create an iterator from the specified variable
error codes
- SGS_EBOUNDS: index out of bounds
- SGS_ENOTSUP: variable type does not support iterators (only objects support them)
- SGS_ENOTFND: object type does not support iterators (iterator conversion request failed)
- any other code can be returned by the object
sgs_IterAdvance(P) [functions]
SGSMIXED sgs_IterAdvance( sgs_Context* C, sgs_StkIdx item )
SGSMIXED sgs_IterAdvanceP( sgs_Context* C, sgs_Variable* var )
advance the iterator to the next position, returning if the current position is still in range or an error code on failure
- this is the way it's expected to be usually called:
while( sgs_IterAdvance( C, item ) > 0 ){ ... sgs_IterPushData ... }
- see Iterator system for more info about iterators
error codes
- SGS_EBOUNDS: index out of bounds
- SGS_EINVAL: iterated object changed in a way that iterator does not support (currently a size equality test)
- SGS_EINPROC: internal failure in the object interface
sgs_IterPushData(P) [functions]
SGSRESULT sgs_IterPushData( sgs_Context* C, sgs_StkIdx item, int key, int value )
SGSRESULT sgs_IterPushDataP( sgs_Context* C, sgs_Variable* var, int key, int value )
load and push data associated with the current position
key
and value
are booleans that specify if the respective value should be returned
- first the key is pushed, then the value
- if neither
key
nor value
are expected, the call succeeds and doesn't push anything
- see Iterator system for more info about iterators
error codes
- SGS_EBOUNDS: index out of bounds
- SGS_EINVAL: iterated object changed in a way that iterator does not support
- SGS_EINPROC: internal failure in the object interface
sgs_IterGetData(P) [functions]
SGSRESULT sgs_IterGetData( sgs_Context* C, sgs_StkIdx item, sgs_Variable* key, sgs_Variable* value )
SGSRESULT sgs_IterGetDataP( sgs_Context* C, sgs_Variable* var, sgs_Variable* key, sgs_Variable* value )
load data associated with the current position
key
and value
are variables where the data is written if the pointer is not NULL
- if neither
key
nor value
are expected, the call succeeds and doesn't retrieve anything
- see Iterator system for more info about iterators
error codes
- SGS_EBOUNDS: index out of bounds
- SGS_EINVAL: iterated object changed in a way that iterator does not support
- SGS_EINPROC: internal failure in the object interface
sgs_ArraySize(P) [functions]
SGSMIXED sgs_ArraySize( sgs_Context* C, sgs_StkIdx item )
SGSMIXED sgs_ArraySizeP( sgs_Context* C, sgs_Variable* var )
check if the specified stack item or variable is an array and return its size or error code on failure
error codes
- SGS_EINVAL: index out of bounds / variable was not an array
sgs_StackSize [function]
sgs_StkIdx sgs_StackSize( sgs_Context* C )
return the size of the current stack frame
sgs_SetStackSize [function]
SGSRESULT sgs_SetStackSize( sgs_Context* C, sgs_StkIdx size )
resizes the current stack frame to fit the specified amount of items
- if the current number of items is less than needed, stack is null-variable-padded at the end
- if the current number of items is more than needed, the unnecessary amount of items is popped
sgs_AbsIndex [function]
sgs_StkIdx sgs_AbsIndex( sgs_Context* C, sgs_StkIdx item )
attempt to convert a negative stack index into a positive one
this function can still return negative values - make sure that valid values are passed to it or check if the returned value is in the range [ 0; stack_frame_size )
sgs_IsValidIndex [function]
SGSBOOL sgs_IsValidIndex( sgs_Context* C, sgs_StkIdx item )
return whether the specified stack index points to an item in the current stack frame
- both positive (first = 0) and negative (last = -1) indices are supported
sgs_PeekStackItem [function]
SGSBOOL sgs_PeekStackItem( sgs_Context* C, sgs_StkIdx item, sgs_Variable* out )
write the data of the specified stack variable if the index is valid
this function does not acquire the variable and thus CANNOT be used in functions that modify it, such as sgs_Assign or sgs_To***; to acquire variable on retrieval, see sgs_GetStackItem or sgs_Acquire
- function returns whether the stack index was valid
sgs_GetStackItem [function]
SGSBOOL sgs_GetStackItem( sgs_Context* C, sgs_StkIdx item, sgs_Variable* out )
write the data of the specified stack variable and increments its reference count if the index is valid
- function returns whether the stack index was valid
sgs_SetStackItem [function]
SGSRESULT sgs_SetStackItem( sgs_Context* C, sgs_StkIdx item, sgs_Variable* val )
copy the specified variable to the specified position in stack
error codes
- SGS_EINVAL: invalid variable type detected (corrupted data)
- SGS_EBOUNDS: index out of bounds
sgs_ItemType [function]
uint32_t sgs_ItemType( sgs_Context* C, sgs_StkIdx item )
return the type ID of the specified stack item
- return value will be equal to one of the SGS_VT_* macro
- if index is invalid, return value will be 0 (SGS_VT_NULL)
sgs_Acquire(Array) [function]
void sgs_Acquire( sgs_Context* C, sgs_Variable* var )
void sgs_AcquireArray( sgs_Context* C, sgs_Variable* var, sgs_SizeVal count )
increment the reference count of the specified variables (if they count references)
sgs_Release(Array) [function]
void sgs_Release( sgs_Context* C, sgs_Variable* var )
void sgs_ReleaseArray( sgs_Context* C, sgs_Variable* var, sgs_SizeVal count )
decrement and possibly deallocate the reference count of the specified variables (if they count references)
- works differently while GC is running: doesn't delete objects of same context in destructor
sgs_GCMark(Array) [function]
SGSRESULT sgs_GCMark( sgs_Context* C, sgs_Variable* var )
SGSRESULT sgs_GCMarkArray( sgs_Context* C, sgs_Variable* var, sgs_SizeVal count )
mark the specified variables as reachable for the garbage collector
- to be called in the GCMARK object callback
sgs_ObjAcquire [function]
void sgs_ObjAcquire( sgs_Context* C, sgs_VarObj* obj )
increment reference count of the specified object
sgs_ObjRelease [function]
void sgs_ObjRelease( sgs_Context* C, sgs_VarObj* obj )
decrement reference count and possibly delete the specified object
sgs_ObjGCMark [function]
SGSRESULT sgs_ObjGCMark( sgs_Context* C, sgs_VarObj* obj )
mark the specified object as accessible to avoid its destruction by the Garbage collection system
- to be called in the GCMARK object callback
sgs_ObjAssign [function]
void sgs_ObjAssign( sgs_Context* C, sgs_VarObj** dest, sgs_VarObj* src )
assign object pointer, handling acquisition/release properly
*dest
and src
must be NULL or valid pointers to objects
- if
src
is not NULL, it is acquired
- if
*dest
is not NULL, it is released
- after the function call,
*dest
is equal to src
sgs_ObjCallDtor [function]
void sgs_ObjCallDtor( sgs_Context* C, sgs_VarObj* obj )
call the DESTRUCT object callback
- this function is to be used in cases where objects are owned by a single entity but have handles all over the place - calling this function would not delete the object but would free its resources, thus leaving handles intact, with their states updated
sgs_GetStringPtr(P) [functions]
char* sgs_GetStringPtr( sgs_Context* C, sgs_StkIdx item )
return the string data pointer of the specified stack item
char* sgs_GetStringPtrP( sgs_Context* C, sgs_Variable* var )
return the string data pointer of the specified variable
- if item is out of bounds or not a string, NULL will be returned and ...
- in a debug build, one of the BreakIf macros will go off and stop the action
sgs_GetStringSize(P) [functions]
sgs_SizeVal sgs_GetStringSize( sgs_Context* C, sgs_StkIdx item )
return the string size of the specified stack item
sgs_SizeVal sgs_GetStringSizeP( sgs_Context* C, sgs_Variable* var )
return the string size of the specified variable
- if item is out of bounds or not a string, 0 will be returned and ...
- in a debug build, one of the BreakIf macros will go off and stop the action
sgs_GetObjectStruct(P) [functions]
sgs_VarObj* sgs_GetObjectStruct( sgs_Context* C, sgs_StkIdx item )
return the object's internal data pointer of the specified stack item
sgs_VarObj* sgs_GetObjectStructP( sgs_Context* C, sgs_Variable* var )
return the object's internal data pointer of the specified variable
- if item is out of bounds or not an object, NULL will be returned and ...
- in a debug build, one of the BreakIf macros will go off and stop the action
sgs_GetObjectData(P) [functions]
void* sgs_GetObjectData( sgs_Context* C, sgs_StkIdx item )
return the object data pointer of the specified stack item
void* sgs_GetObjectDataP( sgs_Context* C, sgs_Variable* var )
return the object data pointer of the specified variable
- if item is out of bounds or not an object, NULL will be returned and ...
- in a debug build, one of the BreakIf macros will go off and stop the action
sgs_GetObjectIface(P) [functions]
sgs_ObjInterface* sgs_GetObjectIface( sgs_Context* C, sgs_StkIdx item )
return the object interface pointer of the specified stack item
sgs_ObjInterface* sgs_GetObjectIfaceP( sgs_Context* C, sgs_Variable* var )
return the object interface pointer of the specified variable
- if item is out of bounds or not an object, NULL will be returned and ...
- in a debug build, one of the BreakIf macros will go off and stop the action
sgs_SetObjectData(P) [functions]
int sgs_SetObjectData( sgs_Context* C, sgs_StkIdx item, void* data )
set the object data pointer of the specified stack item
int sgs_SetObjectDataP( sgs_Context* C, sgs_Variable* var, void* data )
set the object data pointer of the specified variable
- if item is out of bounds or not an object, pointer will not be set, 0 will be returned and ...
- in a debug build, one of the BreakIf macros will go off and stop the action
sgs_SetObjectIface(P) [functions]
int sgs_SetObjectIface( sgs_Context* C, sgs_StkIdx item, sgs_ObjInterface* iface )
set the object interface pointer of the specified stack item
int sgs_SetObjectIfaceP( sgs_Context* C, sgs_Variable* var, sgs_ObjInterface* iface )
set the object interface pointer of the specified variable
- if item is out of bounds or not an object, pointer will not be set, 0 will be returned and ...
- in a debug build, one of the BreakIf macros will go off and stop the action
sgs_StdOutputFunc [function]
void sgs_StdOutputFunc( void* userdata, sgs_Context* C, const void* ptr, size_t size )
standard output function assumes userdata to be FILE* type and writes the passed buffer to it
sgs_Get(Err)OutputFunc [function]
void sgs_GetOutputFunc( sgs_Context* C, sgs_OutputFunc* outfunc, void** outuserdata )
void sgs_GetErrOutputFunc( sgs_Context* C, sgs_OutputFunc* outfunc, void** outuserdata )
retrieves the currently set (error) output function
- validity of the returned function pointer is assured as long as engine internals are not touched anywhere
sgs_Set(Err)OutputFunc [function]
void sgs_SetOutputFunc( sgs_Context* C, sgs_OutputFunc func, void* userdata )
void sgs_SetErrOutputFunc( sgs_Context* C, sgs_OutputFunc func, void* userdata )
sets the function used in 'print'/'errprint' function family
- default output function can be set by passing SGSOUTPUTFN_DEFAULT to func with userdata as FILE*, allocated using the same C runtime that SGScript uses
- default implementation - sgs_StdOutputFunc - copies data to FILE* stream, specified in userdata
- to use this function with non-default (stderr) stream, pass it explicity due to the possibility of having different runtime libraries linked to different binaries
sgs_(Err)Write [function]
void sgs_Write( sgs_Context* C, const void* ptr, sgs_SizeVal size )
void sgs_ErrWrite( sgs_Context* C, const void* ptr, sgs_SizeVal size )
passes the specified data to the (error) output function
- the default output function prints the data to the specified FILE* stream (stdout/stderr by default)
sgs_(Err)WriteStr [function alias]
void sgs_WriteStr( sgs_Context* C, const char* str )
void sgs_ErrWriteStr( sgs_Context* C, const char* str )
passes the specified string to the (error) output function
- alias to
sgs_(Err)Write( C, str, SGS_STRINGLENGTHFUNC( str ) )
sgs_(Err)Writef [function]
void sgs_Writef( sgs_Context* C, const char* what, ... )
passes the arguments through a vsprintf-like function to expand the data and passes it to the specified output function
sgs_StdMsgFunc(_NoAbort) [functions]
void sgs_StdMsgFunc( void* ctx, sgs_Context* C, int type, const char* msg )
void sgs_StdMsgFunc_NoAbort( void* ctx, sgs_Context* C, int type, const char* msg )
writes error info with sgs_WriteErrorInfo to userdata with fprintf, assuming userdata is FILE*
sgs_GetMsgFunc [function]
void sgs_GetMsgFunc( sgs_Context* C, sgs_MsgFunc* outfunc, void** outuserdata )
retrieves the currently set messaging function
- info about the system is at the Messaging system page
- validity of the returned function pointer is assured as long as engine internals are not touched anywhere
sgs_SetMsgFunc [function]
void sgs_SetMsgFunc( sgs_Context* C, sgs_MsgFunc func, void* userdata )
sets the function that handles and prints messages (more commonly, warnings and errors), while still being physically in that context
- info about the system is at the Messaging system page
- both subtypes of the default messaging function can be set by passing these flags for
func
- 'SGSMSGFN_DEFAULT' - default behavior (write stack frame, write error, abort on SGS_ERROR)
- 'SGSMSGFN_DEFAULT_NOABORT' - default behavior without the abort-on-errors feature
- default implementations - sgs_StdMsgFunc(_NoAbort) passes error and stack trace to @sgs_ErrWrite<sgs_(Err)Write)
sgs_Msg [function]
int sgs_Msg( sgs_Context* C, int type, const char* what, ... )
prepares and prints the error specified
- info about the system is at the Messaging system page
type
is the output code (SGS_WARNING, SGS_ERROR etc.)
what
is the error text
- additional function name prefix can be specified with sgs_FuncName or the SGSFN/SGSBASEFN macros
what
, the function name prefix (if set) and the variable arguments are passed to a vsprintf-like function so printf syntax rules apply
- function always returns 0 to be compatible with most error handling cases in C functions: "return sgs_Msg( ... );"
sgs_WriteErrorInfo [function]
void sgs_WriteErrorInfo( sgs_Context* C, int flags, sgs_ErrorOutputFunc func, void* ctx, int type, const char* msg )
writes error info using the error output function specified
the error output function type has the following definition:
typedef int (*sgs_ErrorOutputFunc) ( void*, const char*, ... );
- error output function has the same type as fprintf, sgs_Writef and sgs_ErrWritef
type
and msg
should be passed from the messaging callback - they are the same type number / error message
flags
should be one of SGS_ERRORINFO_STACK, SGS_ERRORINFO_ERROR, SGS_ERRORINFO_FULL
- SGS_ERRORINFO_STACK only writes the stack frame
- SGS_ERRORINFO_ERROR only writes the error message
- SGS_ERRORINFO_FULL writes both
sgs_PushErrorInfo [function]
void sgs_PushErrorInfo( sgs_Context* C, int flags, int type, const char* msg )
pushes a string generated from error info
type
and msg
should be passed from the messaging callback - they are the same type number / error message
flags
should be one of SGS_ERRORINFO_STACK, SGS_ERRORINFO_ERROR, SGS_ERRORINFO_FULL
- SGS_ERRORINFO_STACK only writes the stack frame
- SGS_ERRORINFO_ERROR only writes the error message
- SGS_ERRORINFO_FULL writes both
sgs_HasFuncName [function]
int sgs_HasFuncName( sgs_Context* C )
checks if the currently executed function (last stack frame) has a name literal set
sgs_FuncName [function]
void sgs_FuncName( sgs_Context* C, const char* fnliteral )
sets the function name string for the currently executed function (last stack frame)
- the argument is expected to stay alive for the duration of the function call
- this makes string literals safe for the call, everything else should be avoided
SGSFN [function alias]
void SGSFN( const char* fnliteral )
sets the function name string, more info at sgs_FuncName
- alias for
sgs_FuncName( <implicit> C, fnliteral )
SGSBASEFN [function alias]
void SGSBASEFN( const char* fnliteral )
sets the function name string if it hasn't already been set for the function
- alias for
if( !sgs_HasFuncName( <implicit> C ) ) sgs_FuncName( <implicit> C, x )
sgs_SetHookFunc [function]
void sgs_SetHookFunc( sgs_Context* C, sgs_HookFunc func, void* ctx )
sets the hook function and user data pointer
- hook function is called on function entry, exit and instruction change events
- setting a new hook function disables the one that was set before (if any)
sgs_GetHookFunc [function]
SGSBOOL sgs_GetHookFunc( sgs_Context* C, sgs_HookFunc* outfunc, void** outctx )
writes the hook function and user data pointer that was set (if any), returns whether anything was written
sgs_DefaultMemFunc [function]
void* sgs_DefaultMemFunc( void* userdata, void* ptr, size_t size )
the default memory allocation function
expected behavior: same as for sgs_Memory
sample implementation (same as in sgscript.h):
if( ptr && size ) return realloc( ptr, size );
else if( size ) return malloc( size );
if( ptr ) free( ptr );
return NULL;
sgs_Memory [function]
void sgs_Memory( sgs_Context* C, void* ptr, size_t size )
allocates and frees memory, as specified in arguments
- there are four possible cases that are handled by the function:
ptr
!= NULL, size
!= 0: ptr
is reallocated with new size, keeping as much data as possible, new block of memory is returned
ptr
!= NULL, size
== 0: ptr
is freed, NULL is returned
ptr
== NULL, size
!= 0: a new block of memory is allocated and returned
ptr
== NULL, size
== 0: nothing is done, NULL is returned
Memory allocation macros [macros]
Memory allocation macros
these macros allow slightly simplified handling of memory
sgs_Malloc( C, size )
: allocates the memory (alias to sgs_Memory( C, NULL, size )
)
sgs_Free( C, ptr )
: frees the memory (alias to sgs_Memory( C, ptr, 0 )
)
- sgs_Realloc: alias to sgs_Memory
- the following macros expect that the variable sgs_Context* C is in the scope
sgs_Alloc( what )
: allocates enough memory to fit the specified type what
sgs_Alloc_n( what, n )
: allocates enough memory to fit n
instances of the specified type what
sgs_Alloc_a( what, app )
: allocates enough memory to fit the specified type what
and app
more bytes
sgs_Dealloc( ptr )
: frees the memory
- all of these functions, including sgs_Memory, work on the same heap, thus they are interchangeable
sgs_CodeString [function]
const char* sgs_CodeString( int type, int val )
returns a string for the enumeration type
value val
- there are 4 enumerations to have value names returned for:
- SGS_CODE_ER: error codes (SGS_ERROR, SGS_WARNING, ...)
- SGS_CODE_VT: variable types (SGS_VT_BOOL, SGS_VT_FUNC, ...)
- SGS_CODE_OP: VM instructions (SGS_SI_PUSH, SGS_SI_FORPREP, ... [internal])
sgs_Abort [function]
SGSRESULT sgs_Abort( sgs_Context* C )
stops execution of current SGS functions up to the last C function in the stack, excluding the current
error codes
- SGS_ENOTFND: last or next to last function in the stack was not a SGS function
sgs_Stat [function]
ptrdiff_t sgs_Stat( sgs_Context* C, int type )
returns or prints information about state of SGScript VM
- the following
type
values are supported:
- SGS_STAT_VERSION: returns the version number of the VM
- SGS_STAT_APIVERSION: returns the API version numver of the VM
- SGS_STAT_OBJCOUNT: returns the number of objects created in the VM
- SGS_STAT_MEMSIZE: returns the number of bytes allocated through this SGScript context
- SGS_STAT_NUMALLOCS: returns the number of memory allocations (incremented on each alloc/realloc)
- SGS_STAT_NUMFREES: returns the number of memory frees (incremented on each free/realloc)
- SGS_STAT_NUMBLOCKS: number of memory blocks currently allocated (incremented on alloc, decremented on free)
- SGS_STAT_DUMP_STACK: prints all of the variables in the stack
- SGS_STAT_DUMP_GLOBALS: prints all variables in the global dictionary
- SGS_STAT_DUMP_OBJECTS: prints all objects in the context
- SGS_STAT_DUMP_FRAMES: prints all functions in the call stack
- SGS_STAT_DUMP_STATS: dump some info about memory and objects
- SGS_STAT_XDUMP_STACK: verbosely dumps all of the variables in the stack (extended info, may be much longer)
- tips:
- compare return value of SGS_STAT_VERSION against SGS_VERSION_INT if the code is version-sensitive
- compare return value of SGS_STATE_APIVERSION against SGS_API_VERSION if dynamic loading is used and multiple versions should be supported
sgs_Cntl [function]
int32_t sgs_Cntl( sgs_Context* C, int what, int32_t val )
modifies the state of the VM or returns info about it
- the following
what
values are supported:
- SGS_CNTL_STATE: sets the new compilation state from
val
, returns the previous value
- SGS_CNTL_GET_STATE: returns the currently set compilation state
- SGS_CNTL_MINLEV: sets the new minimum error level from
val
, returns the previous value
- SGS_CNTL_GET_MINLEV: returns the currently set minimum error level
- SGS_CNTL_ERRNO: if
val
is true, sets internal errno to 0, otherwise - to errno
, returns the previous value
- SGS_CNTL_SET_ERRNO: sets internal errno to
val
, returns the previous value
- SGS_CNTL_GET_ERRNO: returns the currently set internal errno
- SGS_CNTL_ERRSUP: sets error suppression lock count to
val
, returns the previous value
- SGS_CNTL_GET_ERRSUP: returns the currently set error suppression lock count for the last stack frame
- everything else does nothing and returns 0
sgs_StackFrameInfo [function]
void sgs_StackFrameInfo( sgs_Context* C, sgs_StackFrame* frame, const char** name, const char** file, int* line )
helps to retrieve file name, function name and line number of the specified stack frame
- each non-NULL pointer is initialized with valid data; even if it may not be very helpful (for example, all anonymous functions get the same name - "<anonymous function>")
sgs_GetFramePtr [function]
sgs_StackFrame* sgs_GetFramePtr( sgs_Context* C, int end )
returns a call stack frame pointer
- if
end
is not 0, pointer to topmost frame is returned, otherwise a pointer to first frame is returned
sgs_Errno [function alias]
int sgs_Errno( sgs_Context* C, int clear )
copies errno to internal errno value if clear
is not 0, otherwise internal errno value is set to 0, returns clear
- used with a boolean expression and chaining to set errno if the expression returned false, like this:
sgs_PushBool( C, sgs_Errno( C, rename( a, b ) == 0 ) )
sgs_SetErrno [function alias]
int sgs_SetErrno( sgs_Context* C, int err )
sets a specific value err
to the internal errno variable
- alias to
sgs_Cntl( C, SGS_CNTL_SET_ERRNO, err )
sgs_GetLastErrno [function alias]
int sgs_GetLastErrno( sgs_Context* C )
returns the currently set internal errno variable
- alias to
sgs_Cntl( C, SGS_CNTL_GET_ERRNO, 0 )
sgs_PushStringBuf32 [function]
void sgs_PushStringBuf32( sgs_Context* C, sgs_String32* S, const char* str, sgs_SizeVal len )
pushes a temporary string variable from the specified buffer, allocated in the sgs_String32
object
- string buffer must be freed from all contexts before the memory it's allocated on is released
len
is limited to 31 character
sgs_PushString32 [function]
void sgs_PushString32( sgs_Context* C, sgs_String32* S, const char* str )
pushes a temporary string variable from the specified string, allocated in the sgs_String32
object
- string buffer must be freed from all contexts before the memory it's allocated on is released
- alias to
sgs_PushStringBuf32( C, S, str, SGS_STRINGLENGTHFUNC(str) )
sgs_CheckString32 [function]
void sgs_CheckString32( sgs_String32* S )
attempts to trigger a debug breakpoint if the specified temporary string object is not freed from all contexts
- internal function
sgs_BreakIf
is used
sgs_IsFreedString32 [function]
SGSBOOL sgs_IsFreedString32( sgs_String32* S )
returns whether the specified temporary string object is freed from all contexts
- for usage with custom error outputs / assertion systems
C Functions
A C function has the type int CFunc( sgs_Context* )
. It receives the context that called it and must return the number of return values pushed on stack.
Conventions
There are no forced courses of action beyond this point. However, to simplify development, some conventions were established and are used throughout the standard library and are suggested to follow.
General structure
- the usage of SGS_CTX in argument list is suggested to enable the use of certain macros that assume the availability of
sgs_Context* C
- there are no restrictions on function names, however it helps to mark the scripting engine functions with a common prefix and if they wrap a native function, including the name of the wrapped function is suggested
Argument loading
- prefer using sgs_LoadArgs, followed by sgs_LoadArgsExt, followed by the sgs_Parse***/sgs_Is***/sgs_ItemType(Ext)/... functions together with ArgError function family for error handling
Error handling
- it is preferred to do most of it at the beginning, before custom allocations (VM stack doesn't count here), where it is possible to just
return sgs_Msg( C, SGS_WARNING, "Error message" )
- SGS_WARNING is for non-fatal errors, SGS_ERROR is for errors that make it impossible to continue (severe, undoubted logical errors fall into this category)
- on error, functions should return nothing or null
A typical function
int sgsfunc_sample( SGS_CTX )
{
sgs_Int num;
char* str;
char* buf;
sgs_SizeVal bufsize;
if( !sgs_LoadArgs( C, "ism", &num, &str, &buf, &bufsize ) )
return 0;
if( bufsize == 0 )
return sgs_Msg( C, SGS_WARNING, "buffer cannot be empty" );
// sgs_Msg always returns 0
// .. do something with the passed arguments ..
// anything can be returned ..
// .. but in this case, we want to say ..
// .. that the action was successful
sgs_PushBool( C, 1 );
return 1;
}
Object interface
Every interface function has the type int ObjCallback ( sgs_Context* C, sgs_VarObj* data, ... )
. Not every of them has to be implemented (none of them are required) but for all non-pointer objects it helps to have at least one of them.
Interface is a structure that contains of an array and 10 function pointers in the following order: destruct, gcmark, getindex, setindex, convert, serialize, dump, getnext, call, expr. This is how interfaces are usually defined in code:
sgs_ObjInterface object_interface[1] =
{{
"object_type_name",
object_destruct, NULL, /* destruct, gcmark */
object_getindex, NULL, /* getindex, setindex */
NULL, NULL, NULL, NULL, /* convert, serialize, dump, getnext */
NULL, NULL /* call, expr */
}};
The interface is defined as an array with size=1 to later be able to use it in code without prepending "&" to the name.
DESTRUCT - destruction callback
When called:
Additional arguments:
None.
Stack frame:
Empty.
Return values:
Non-negative value if successful, negative on error.
Additional notes:
It is important to minimize the possibility of failure here. The system cannot help in any way if memory or ownership states are corrupted.
GETINDEX - index/property retrieval callback
When called:
- On A[B] (index) and A.B (property) reads in SGScript.
- Index/Property/Path function families in the C API.
Additional arguments:
- sgs_Variable* key -- key variable to be used to find a sub-item
- int isprop -- (0/1) whether this is a property read (1) or index read (0)
Stack frame:
Empty at beginning. Expected to have at least one item on stack after a successful index/property read. The topmost one is used.
Return values:
- Non-negative value if successful, negative on error.
- Use SGS_ENOTFND if the specified index/property was not found.
Additional notes:
It is safe to use conversion functions on the key variable.
SETINDEX - index/property setting callback
When called:
- On A[B] (index) and A.B (property) writes in SGScript.
- Index/Property/Path function families in the C API.
Additional arguments:
- sgs_Variable* key -- key variable to be used to find a sub-item
- sgs_Variable* value -- value variable to be used in setting the value of the sub-item
- int isprop -- (0/1) whether this is a property read (1) or index read (0)
Stack frame:
Empty.
Return values:
- Non-negative value if successful, negative on error.
- Use SGS_ENOTFND if the specified index/property was not found.
- Use SGS_EINVAL if the given value could not be used.
Additional notes:
It is safe to use conversion functions on both variables.
CONVERT - conversion callback
When called:
Depending on the argument, it is called by different sources:
Additional arguments:
- int type -- one of SGS_VT_[BOOL|INT|REAL|STRING|PTR] or SGS_CONVOP_CLONE / SGS_CONVOP_TYPEOF / SGS_CONVOP_TOITER
Stack frame:
Empty at beginning. Expected to have at least one item on stack after a successful conversion. The topmost one is used.
Depending on the argument, it requires different variable types on stack:
- type conversions require a value of the right type.
- SGS_CONVOP_CLONE should return an exact copy of the same object
- SGS_CONVOP_TYPEOF should return a string containing the type name
- SGS_CONVOP_TOITER should return an object with a GETNEXT callback
Return values:
- Non-negative value if successful, negative on error.
- Use SGS_ENOTSUP if specified conversion is not supported.
Additional notes:
- It should be safe to give the wrong variable type but errors may not be triggered in such cases.
SERIALIZE - serialization callback
When called:
Additional arguments:
None.
Stack frame:
Empty.
Return values:
- Non-negative value if successful, negative on error.
Additional notes:
Callback requires no data but expects that sgs_Serialize / sgs_SerializeObject is successfully called once. In the case of sgs_SerializeObject, the necessary number (equal to argument count, passed to the function) of sgs_Serialize calls must be made before it.
DUMP - debug dump callback
When called:
Additional arguments:
- int maxdepth -- remaining recursion depth of dump to be passed on to sgs_DumpVar calls.
Stack frame:
Empty at beginning. Expected to have at least one item on stack after a successful conversion. The topmost one is used.
Return values:
- Non-negative value if successful, negative on error.
Additional notes:
- Callback expects a string variable on the top of the stack.
- sgs_DumpVar with maxdepth <= 0 returns "...", so it is not necessary to handle such cases beyond passing the parameter.
GCMARK - garbage collector marking callback
When called:
Additional arguments:
None.
Stack frame:
Empty.
Return values:
- Non-negative value if successful, negative on error.
Additional notes:
- Callback expects that sgs_GCMark is called on all of the owned variables.
- It is important to minimize the possibility of failure here. The system cannot help in any way if memory or ownership states are corrupted.
GETNEXT - iterator control callback
When called:
Additional arguments:
- int act -- specifies the actions that should be taken in this call.
- if argument == 0, iterator's position must be increased by one step and the return value must contain whether iterator has not reached end (positive value if so, otherwise - 0) or an error if callback has failed
- otherwise, callback must push the data required (if SGS_GETNEXT_KEY is set, the key, and if SGS_GETNEXT_VALUE is set - the value, in exactly that order)
Stack frame:
Empty at beginning. Expects at least one (if either flag is set, but not both) or two (if both flags are set) variables on success. Key first, value second.
Return values:
- Non-negative value if successful, negative on error.
- if argument == 0, must return whether iterator has not reached end (positive value if so, otherwise - 0)
Additional notes:
None.
CALL - the "function call" callback
When called:
- when an object is used like a function
object_variable( .. )
in SGScript
- Call function family in the C API
Additional arguments:
None.
Stack frame:
Contains all the same things as any C function call would: optional this
variable and optional argument list. Expects at least the returned number of items after the call to be used as return values.
Return values:
- Non-negative value if successful, negative on error.
- On success, the number returned is the number of variables returned by the function.
Additional notes:
None.
EXPR - expression callback
When called:
- On arithmetic operations with the object as one or both operands in SGScript.
- On sgs_ArithOp in the C API.
Additional arguments:
- sgs_Variable* A - the first (left side) operand or the only one in case of SGS_EOP_NEGATE
- sgs_Variable* B - the second (right side) operand or NULL in case of SGS_EOP_NEGATE
- int op - operation type, one of SGS_EOP_[ADD|SUB|MUL|DIV|MOD|COMPARE|NEGATE]
Stack frame:
Empty at beginning. Expects at least one variable on success (the topmost one will be used).
Return values:
- Non-negative value if successful, negative on error.
Additional notes:
- SGS_EOP_COMPARE expects int/real value: >0 if A > B, <0 if A < B, =0 if A = B
The full list of operators triggering the operations:
- SGS_EOP_ADD: binary +, +=
- SGS_EOP_SUB: binary -, -=
- SGS_EOP_MUL: *, *=
- SGS_EOP_DIV: /, /=
- SGS_EOP_MOD: %, %=
- SGS_EOP_COMPARE: <, <=, >, >=, ==, !=, ===, !==
- SGS_EOP_NEGATE: unary -
Interaction with the environment
Most operations are directed towards the scripting engine, that is - environment makes a function call and scripting engine handles it. For everything else, there are callbacks.
Memory allocation
- sgs_MemFunc must be specified in creation of the scripting engine context
- sgs_MemFunc (re)allocates and frees memory
- unlike realloc, if size = 0, this function must return NULL
- sgs_DefaultMemFunc is the sample implementation
- the expected behavior is same as for sgs_Memory
Output
- sgs_MsgFunc and sgs_OutputFunc are responsible for piping the outputs to their destinations
- they can be set at any moment after the creation of the scripting engine context
- sgs_MsgFunc takes the following arguments:
- void* data - the user data pointer
- sgs_Context* C - the scripting engine context
- int type - the debug type (SGS_INFO, SGS_WARNING etc.)
- const char* message - the debug message
- sgs_StdMsgFunc(_NoAbort) are the sample implementations
- sgs_OutputFunc takes the following arguments:
- void* data - the user data pointer
- sgs_Context* C - the scripting engine context
- const void* ptr - the data to write
- sgs_SizeVal size - the size of data to write
- sgs_StdOutputFunc is the sample implementation
Execution notifications
- sgs_HookFunc must be set to retrieve events of that kind
- it can be set at any moment after the creation of the scripting engine context
- sgs_HookFunc takes the following arguments:
- void* data - the user data pointer
- sgs_Context* C - the scripting engine context
- int event - the event that occured, can be one of these values:
- SGS_HOOK_ENTER - function was entered
- SGS_HOOK_EXIT - function was exited
- SGS_HOOK_STEP - instruction is about to be executed
Commonly required advanced tasks
Method handling
- the preferred way to handle methods with a specific object type for
this
:
ObjectDataStruct* data;
if( !SGS_PARSE_METHOD( C, Object_interface_pointer, data, Object_name, Method_name ) )
return 0;
sgs_FuncName( C, "<object>.<method>" );
if( !sgs_Method( C ) || !sgs_IsObject( C, 0, Object_interface_pointer ) )
return sgs_ArgErrorExt( C, 0, 1, "<object>", "" );
ObjectDataStruct* data = (ObjectDataStruct*) sgs_GetObjectData( C, 0 );
sgs_HideThis( C );
- the OLD way, version 2: Method + function handling (function that can be called as a method too)
int method_call = sgs_Method( C );
sgs_FuncName( C, method_call ? "<object>.<method>" : "<object_function>" );
if( !sgs_IsObject( C, 0, Object_interface_pointer ) )
return sgs_ArgErrorExt( C, 0, method_call, "<object>", "" );
ObjectDataStruct* data = (ObjectDataStruct*) sgs_GetObjectData( C, 0 );
sgs_ForceHideThis( C );
- the reason why the first method is preferred to others is: it's shorter, does pretty much the same thing and resolves to sgs_ParseMethod, which allows sharing more code and rebuilding the SGS_PARSE_METHOD macro abstraction, if necessary
Standard library reference
Core library
This library is loaded on initialization and contains the functions and constants necessary to do primary actions:
- execution of additional scripts
- creating and using array, class, dict, map, closure
- converting between variables
- serialization / deserialization
- operation control
- error handling and throwing
- global environment modification
- standard input / output
- data debugging
Functions:
- containers
- array - returns an array containing the specified variables
- dict - returns a key-value map object (string keys) containing the specified variables
- map - returns a key-value map object (many key types) containing the specified variables
- class - returns an index fallback / overloading object, linking both specified variables
- array_filter - returns an array that is filtered with a truth test or the specified function
- array_process - convert all array elements by a function
- dict_filter - returns a dict object that is filtered with a truth test or the specified function
- dict_process - convert all dictionary elements by a function
- dict_size - returns the number of items in a dict
- map_size - returns the number of items in a map
- isset - checks if the specified property is available
- unset - unsets the specified property (only for dict/map objects)
- clone - returns the cloned variable or the same if immutable
- get_keys - returns an array of keys from an iterable
- get_values - returns an array of values from an iterable
- get_concat - returns an array with all values from all iterables concatenated together in order
- get_merged - returns a dict with all mappings merged
- get_merged_map - returns a map with all mappings merged
- get_iterator - returns an iterator from the passed object, if it has one
- iter_advance - advances an iterator to the next position, returning if there is any more data to read
- iter_getdata - returns key/value data from iterator
- type info and conversion
- tobool - returns a variable, converted to boolean
- toint - returns a variable, converted to an integer
- toreal - returns a variable, converted to a real value
- tostring - returns a variable, converted to a string
- toptr - returns a variable, converted to pointer
- parseint - try to parse a variable as integer, return the value or null on failure
- parsereal - try to parse a variable as string, return the value or null on failure
- typeof - returns the type string of a variable
- typeid - returns type ID of a variable
- typeptr - returns type interface pointer from object variables
- typeptr_by_name - returns type interface pointer by its name
- is_numeric - returns if variable is a numeric type
- is_callable - returns if variable can be called as a function
- is_array - returns if variable is an array
- is_dict - returns if variable is a dict
- is_map - returns if variable is a map
- is_iterable - returns if variable is iterable
- input/output
- operating system
- ftime - returns an always increasing time value, in seconds, as a real value
- utilities
- rand - returns a random integer between 0 and RAND_MAX
- randf - returns a random real value between 0 and 1
- srand - reseed random number generator
- hash_fnv - generate a hash using the FNV-1a algorithm
- hash_crc32 - generate a hash/checksum using the crc32 algorithm
- SGS-specific utilities
- va_get_args - returns an array of all arguments passed to calling function
- va_get_arg - returns one of the arguments passed to calling function
- va_arg_count - returns the number of all arguments passed to calling function
- sys_call - call a function/callable dynamically (function and
this
specified at runtime)
- sys_apply - call a function/callable even more dynamically (argument count also specified at runtime)
- pcall - do a protected call by trapping all internal messages in the specified callback
- assert - emit an error if a condition does not evaluate to
true
- eval - compile and run script code, retrieve return values
- eval_file - compile and rune script file, retrieve return values
- compile_sgs - compile script code
- include_library - load a built-in library
- include_file - load a script file
- include_shared - load a dynamically linked library / shared object (.DLL/.SO)
- import_cfunc - load a C function from .DLL/.SO
- include - load many types of files
- sys_curfile - returns the origin file of the calling function
- sys_curfiledir - returns the directory of the origin file of the calling function
- sys_backtrace - returns call stack info
- sys_msg - emit a system message
- INFO - emit an INFO message
- WARNING - emit a WARNING message
- ERROR - emit an ERROR message
- sys_abort - stop the execution of the calling SGS function
- app_abort - abort execution of application (exit application immediately with an error)
- app_exit - exit application immediately
- sys_replevel - change the minimum message reporting level
- sys_stat - write info about system state
- errno - return current errno value as number or string
- errno_string - return specified or current errno value as string
- errno_value - return the errno value corresponding to the name
- dumpvar - returns the dump string of variables
- dumpvar_ext - returns the dump string of a variable, optionally specifying max. recursion depth
- gc_collect - run the garbage collector to remove inaccessible objects
- serialize - returns a byte buffer containing info necessary to later recreate variable structure
- unserialize - recreate variable structure from a byte buffer
Objects and their methods:
Constants:
Other:
- _G - environment superglobal, a dict containing all global variable names and values; can be changed
array [function]
array( ... )
returns an array, containing the arguments
- similar to the array literal, though somewhat limited
array( "5", 6, 7.0 ) // same as ["5",6,7.0]
dict [function]
dict( [key, value, ...] )
returns a 'dict' (dictionary/hash table) object, containing the even arguments mapped to respective previous arguments
- if no arguments are passed, an empty dictionary is returned
- if an even number of arguments is passed, function returns null and emits a warning
- all even arguments must be strings or convertible to strings
dict( "name", "John", "phone", 1234567890 ); // same as { name = "John", phone = 1234567890 }
map [function]
map( [key, value, ...] )
returns a 'map' (map/hash table) object, containing the even arguments mapped to respective previous arguments
- if no arguments are passed, an empty map is returned
- if an even number of arguments is passed, function returns null and emits a warning
map( "John", "name", 1234567890, "phone" ); // useful for mapping additional data to variables or making sets
class [function]
class( first, second )
returns a class object with first
set as the primary data source and second
set as the secondary/backup data source
- both arguments accept all kinds of variables but it's generally preferred to use only dicts / maps / special objects
- refer to Classes for more information on how class objects work and how to use them
someCommonInterface = { printdata = function(){ print( this.data ); } };
c = class( { data = "5" }, someCommonInterface );
c.data = "6";
c.printdata(); // prints 6
array_filter [function]
array_filter( array[, callable] )
return an array with the items that convert to boolean 'true', optionally preprocessed by a callable
- two arguments are passed to the callable: value, index
array_filter([ 0, 1, 2, 3 ]); // returns [1,2,3]
array_process [function]
array_process( array, callable )
return an array with the items passed through a callable
- two arguments are passed to the callable: value, index
dict_filter [function]
dict_filter( dict[, callable] )
return a dict with the items that convert to boolean 'true', optionally preprocessed by a callable
- two arguments are passed to the callable: value, key
dict_filter({ a = 0, b = 1 }); // returns {b=1}
dict_process [function]
dict_process( dict, callable )
return a dict with the items passed through a callable
- two arguments are passed to the callable: value, key
dict_size [function]
dict_size( dict )
return the number of entries in the dict object
x = { a = 5, b = 123 };
dict_size( x ); // returns 2
map_size [function]
map_size( dict )
return the number of entries in the map object
x = map( 5, "a", 123, "b" );
map_size( x ); // returns 2
isset [function]
isset( var, key )
returns whether a property key
is readable (exists) in variable var
x = { a = 5 };
isset( x, "a" ); // returns 'true'
isset( x, "b" ); // returns 'false'
isset( print, "call" ); // returns 'true' -- works with built-in special properties too
unset [function]
unset( dict|map var, (string) key )
removes an entry named key
from the dictionary var
key
is only required to be of string
type if a dict
is passed
clone [function]
clone( var )
creates a one-reference copy of the variable var
or returns null and emits a warning on failure
- variables that are passed by value (null, bool, int, real, cfunc) or strings/functions are returned as-is, since for value types all copies are same and strings/functions are immutable
x = { a = 5 };
y = clone( x );
z = x;
x.a = 6;
print( y.a ); // prints "5"
print( z.a ); // prints "6"
get_keys [function]
get_keys( iterable var )
returns an array of keys found in the iterable object var
or returns null and emits a warning on failure
var
must be an iterable object (has interface OP_CONVERT defined and successfully handles a CONVOP_TOITER request) - such objects are array
, dict
, map
and io_dir
get_keys( [5,7,0] ); // returns [0,1,2]
get_keys( {b=5,a=2} ); // returns ["b","a"]
get_values [function]
get_values( iterable var )
returns an array of values found in the iterable object var
or returns null and emits a warning on failure
var
must be an iterable object (has interface OP_CONVERT defined and successfully handles a CONVOP_TOITER request) - such objects are array
, dict
, map
and io_dir
get_values( [5,7,0] ); // returns [5,7,0]
get_values( {b=5,a=2} ); // returns [5,2]
get_concat [function]
get_concat( iterable var, iterable var1, ... )
returns an array of values found in all iterable objects passed to the function or returns null and emits a warning on failure
get_concat( [1,2], {a="5",b=8} ); // returns [1,2,"5",8]
get_merged [function]
get_merged( iterable var, iterable var1, ... )
returns a dict of all key-value pairs found in all iterable objects passed to the function or returns null and emits a warning on failure
get_merged( [1,2], [3], {a="4"} ); // return {0=3,1=2,a="4"}
get_merged_map [function]
get_merged_map( iterable var, iterable var1, ... )
returns a map of all key-value pairs found in all iterable objects passed to the function or returns null and emits a warning on failure
get_merged_map( [1,2], map(5,6), {a="4"} ); // return {0=3,1=2,int(5)=6,a="4"}
get_iterator [function]
get_iterator( iterable var )
returns an iterator from the passed object, if it has one
get_iterator( [ 5 ] ); // returns array iterator for the specified array
iter_advance [function]
iter_advance( iterator var )
advances an iterator to the next position, returning if there is any more data to read
it = get_iterator( [ 5 ] ); // retrieves iterator from array [5]
iter_advance( it ); // returns true, indicating that the current position is still a valid one
iter_getdata [function]
iter_getdata( iterator var, bool pushkey = false, bool pushvalue = true )
returns key/value data from iterator
- if key is requested, it is returned first
- if neither key not value are requested,
null
is returned and a warning is emitted
it = get_iterator( [ 5 ] ); // retrieves iterator from array [5]
iter_advance( it ); // returns true, indicating that the current position is still a valid one
(key,value) = iter_getdata( it, true ); // returns 0, 5 -- key, value
tobool [function]
tobool( var )
returns a boolean, generated from variable var
using the Conversion rules
tobool( 5 ); // returns 'true'
tobool( "" ); // returns 'false'
toint [function]
toint( var )
returns an integer, generated from variable var
using the Conversion rules
toint( 5.4 ); // returns 5
toint( "0xff" ); // returns 255
toreal [function]
toreal( var )
returns a real value, generated from variable var
using the Conversion rules
toreal( 5 ); // returns 5.0
toreal( "3e+2" ); // returns 300.0
toreal( "0xff" ); // returns 255.0
tostring [function]
tostring( var )
returns a string value, generated from variable var
using the Conversion rules
tostring( 5 ); // returns "5"
tostring( { "a" = "b" } ); // returns "{a=b}"
toptr [function]
toptr( var )
returns a pointer value, generated from variable var
using the Conversion rules
toptr( 5 ); // returns 5
toptr( "3e+2" ); // returns address of the string
toptr( [] ); // returns address of array data
parseint [function]
parseint( var )
returns an integer, generated from variable var
using the Conversion rules or returns null
on failure
parseint( 5.4 ); // returns 5
parseint( "0xff" ); // returns 255
parseint( parseint ); // returns null
parsereal [function]
parsereal( var )
returns a real value, generated from variable var
using the Conversion rules or returns null
on failure
parsereal( 5 ); // returns 5.0
parsereal( "3e+2" ); // returns 300.0
parsereal( "0xff" ); // returns 255.0
parsereal( parsereal ); // returns null
typeof [function]
typeof( var )
returns the type name of variable var
, as string
- this function is equivalent to sgs_TypeOf in the C API
typeof( 5 ); // returns "real"
typeof( [] ); // returns "array"
typeid [function]
typeid( var )
returns the first 4 bits of the variable var
type flags, as int
- returns one of the values mapped to VT_NULL/VT_BOOL/VT_INT/VT_REAL/VT_STRING/VT_FUNC/VT_CFUNC/VT_OBJECT/VT_PTR
- this function is equivalent to sgs_ItemType in the C API
typeid( 5 ) == VT_INT; // returns 'true'
typeid( [] ); // returns 7 / VT_OBJECT
typeptr [function]
typeptr( var )
returns type interface pointer from object variables or null pointer from other variables
typeptr( 5 ); // returns ptr(0)
typeptr( [] ); // returns ptr(...), NOT ptr(0)
typeptr_by_name [function]
typeptr_by_name( string name )
returns type interface pointer by its name or null pointer if name is not assigned to a pointer
typeptr_by_name( "array" ); // returns ptr(...)
typeptr_by_name( "array" ) == typeptr( [] ); // returns 'true'
is_numeric [function]
is_numeric( var )
returns whether the variable var
is numeric - one of bool/int/real or a numeric string
- all types that can always be converted to numbers are considered numeric, with two exceptions:
- convertible objects are not numeric since validation requires an interface call and unnecessary interface calls cannot be made
- null value is considered to be the lack of a better value, thus it cannot be considered valid, even though it always maps implicitly to the integer 0
is_numeric( 12.124 ); // returns true
is_numeric( "what" ); // returns false
is_callable [function]
is_callable( var )
returns whether the variable var
is callable - a function (func/cfunc) or an object with OP_CALL defined
is_callable( print ); // returns 'true'
is_callable( function(){} ); // returns 'true'
is_callable( 5 ); // returns 'false'
is_array [function]
is_array( var )
returns if variable is an array
is_array( print ); // returns 'false'
is_array( [] ); // returns 'true'
is_dict [function]
is_dict( var )
returns if variable is a dict
is_dict( 5 ); // returns 'false'
is_dict( [] ); // returns 'false'
is_dict( {} ); // returns 'true'
is_map [function]
is_map( var )
returns if variable is a map
is_map( "map" ); // returns 'false'
is_map( {} ); // returns 'false'
is_map( map() ); // returns 'true'
is_iterable [function]
is_iterable( var )
returns if variable is iterable
is_iterable( print ); // returns 'false'
is_iterable( [] ); // returns 'true'
is_iterable( {} ); // returns 'true'
print, println, printlns, errprint, errprintln, errprintlns [functions]
print( ... ), println( ... ), printlns( ... ),
errprint( ... ), errprintln( ... ), errprintlns( ... ),
passes all arguments, converted to strings, to the (error) output callback
- (err)print passes arguments without modifications
- (err)println passes a newline character after all variables
- (err)printlns passes a newline character after each variable
print( 5, "x" ); // prints "5x"
println( 5, "x" ); // prints "5x\n"
printlns( 5, "x" ); // prints "5\nx\n"
errprint( 5, "x" ); // prints "5x" to error output stream
errprintln( 5, "x" ); // prints "5x\n" to error output stream
errprintlns( 5, "x" ); // prints "5\nx\n" to error output stream
printvar_ext [function]
printvar_ext( var, int maxdepth = 5 )
passes a dump of the variable (informative string version) to the output callback, allowing to optionally specify the maximum depth of the dump (how deep it is allowed to look for sub-variables)
printvar_ext( 5 ); // prints "real (5)"
printvar_ext( "wat" ); // prints "string [3] "wat""
printvar_ext( [{a=[{}]}], 2 ); /* prints:
object (003C5F90) [0] array (1)
[
object (003C60A8) [1] dict (1)
{
...
}
]
*/
printvar [function]
printvar( var, ... )
same as a list of printvar(var); calls for each argument
read_stdin [function]
read_stdin( bool all = false )
reads from the standard input
- if
all
is set to 'true', all standard input is read up to EOF (useful for piped input)
- if
all
is set to 'false' or not set at all, input is read up to (and excluding) the next newline character
print "Name: "; name = read_stdin(); // waits for user input
process( read_stdin(true) ); // loads all piped input
ftime [function]
ftime()
returns a value that is increased by a total of 1 each second (time), as real
- guaranteed to offer sub-second precision unless stated otherwise for any specific platform
start = ftime();
do_something_big();
println( "That took " $ ftime() - start $ " seconds." );
rand [function]
rand()
returns a random 'int' value in the range [0;RAND_MAX] - from 0, inclusive, to RAND_MAX, inclusive
randf [function]
randf()
returns a random 'real' value in the range [0;1] - from 0, inclusive, to 1, inclusive
srand [function]
srand( int seed )
specify a different seed value for the built-in pseudo-random number generator
srand( 5 ); // restart the generator with the value specified
srand( ftime() ); // restart the generator depending on the second the code was executed
hash_fnv [function]
hash_fnv( string buf, bool as_hexstring = false )
generate a hash, using the FNV-1a algorithm
- if
as_hexstring
is true, an 8 characters long string containing the hexadecimal fixed-length hash value is returned, otherwise the value is returned as integer
hash_crc32 [function]
hash_crc32( string buf, bool as_hexstring = false )
generate a hash/checksum, using the CRC32 algorithm
- if
as_hexstring
is true, an 8 characters long string containing the hexadecimal fixed-length hash/checksum value is returned, otherwise the value is returned as integer
va_get_args [function]
va_get_args()
return an array containing all arguments passed to the calling function
va_get_arg [function]
va_get_arg()
returns one of the arguments passed to calling function
va_arg_count [function]
va_arg_count()
return the number of arguments passed to the calling function
sys_call [function]
sys_call( func, this[, args..] )
calls the specified function with the specified this
value and argument list
if argument count is only known at runtime, see sys_apply
- C functions, SGS functions, closure objects and real closures have this function under the "call" property
sys_apply [function]
sys_apply( func, this, args )
calls the specified function with the specified this
value and argument array
if argument count is known at compile time, prefer sys_call to this function
- C functions, SGS functions, closure objects and real closures have this function under the "apply" property
pcall [function]
pcall( callable func[, callable errh ])
calls the callable func
, hiding internal errors from the caller or optionally passing them to callable errh
errh
error handler is called with two arguments - int error_type, string message
- and expected to return 0-1 arguments ([int])
- error handler must return 0/null/nothing if the error has been successfully processed or the new error type otherwise
- errors thrown inside the handler will not be caught so any error can be transformed to any other
- an empty function behaves the same way as
pcall
without function
include "string";
function handler( type, msg )
{
if( string_find( msg, "not found" ) !== null )
sys_msg( type, "nooooooooooo" );
}
function handler2( type, msg )
{
if( string_find( msg, "not found" ) !== null )
return SGS_ERROR;
}
pcall(function(){ print x; }); // nothing
pcall(function(){ print x; }, handler ); // renamed warning
pcall(function(){ print x; }, handler2 ); // changed type to error
assert [function]
assert( var condition[, string message] )
if condition evaluates to 'false', emits an error "assertion failed" or if message is defined, "assertion failed: <message>"
assert( text, "text was not defined" );
eval [function]
eval( string code )
returns the result of evaluating the passed code
string as SGScript code
eval("print 5;"); // prints 5
eval_file [function]
eval_file( string filename )
returns the result of evaluating the file pointed to by filename
as SGScript code
eval_file("myfile.sgs"); // ???
compile_sgs [function]
compile_sgs( string code )
returns the generated bytecode or null + error info
- this function is equivalent to sgs_Compile in the C API
compile_sgs( io_file_read( "myfile.sgs" ) ); // ???
include_library [function]
include_library( string lib[, bool override ] )
loads the global variables of the specific library lib
in the state, returns success, as bool
, emits a warning on failure
- lib must be one of 'fmt', 'io', 'math', 'os', 'string'
- if
override
is specified, library will be reloaded even if it was already loaded before
- this function is equivalent to the sgs_LoadLib_* functions in the C API
printvar( sin ); // warning, null
include_library( "math" );
printvar( sin ); // C function
include_file [function]
include_file( string file[, bool override ] )
executes the file pointed to by file
, returns success, as bool
, emits a warning on failure
- this function does NOT check include paths (SGS_PATH)
- if
override
is specified, file will be reloaded even if it was already loaded before
- this function is equivalent to sgs_ExecFile in the C API
include_file( "something.sgs" ); // loads something
include_file( "something.sgs" ); // does not load it again
include_file( "something.sgs", true ); // loads it again
include_shared [function]
include_shared( string file[, bool override ] )
runs the shared library pointed to by file
, returns success, as bool
, emits a warning on failure
file
must be available according to the platform-specific rules of dynamic libraries (shared objects)
- the library must contain a 'sgscript_main' function that will be called on initialization
- if
override
is specified, file will be reloaded even if it was already loaded before
include_shared( "sgsjson.dll" ); // load the JSON library DLL on Windows
include [function]
include( string file[, bool override ] )
tries to load a library or a file according to the include path
- the order of actions:
- first, a library load is attempted
- on failure, a file is looked for by every entry of the sys_include_path variable (? - the file replacement symbol, | - file directory replacement symbol, ; - separator)
- if file is not found, everything stops
- if file is found, first - a library load is attempted, on failure - bytecode & source code loading
- this function is also available as a replicating statement 'include' (ex. 'include "fmt", "io";' works the same way as include("fmt"); include("io");)
import_cfunc [function]
import_cfunc( string file, string funcname )
retrieves the funcname
function of the shared library file
, returns success, as bool
, emits a warning on failure
Do not call 'sgscript_main' using this function! That function has different return value semantics so at best, something will work, a warning could be emitted and the worst case is that something will crash.
file
must be available according to the platform-specific rules of dynamic libraries (shared objects)
import_cfunc( "mydll.dll", "someSGScriptFunc" )();
sys_curfile [function]
sys_curfile()
returns the path of the file (as passed on load) that contains the currently executed code or null
if the file cannot be determined (eval, C functions)
// a.sgs
print( sys_curfile() ); // prints "a.sgs"
// b.sgs
include "a.sgs";
sys_curfiledir [function]
sys_curfiledir()
returns the directory path of the file (as passed on load) that contains the currently executed code or null
if the file cannot be determined (eval, C functions)
// ext/a.sgs
print( sys_curfiledir() ); // prints "ext"
// a.sgs
print( sys_curfiledir() ); // prints "."
// b.sgs
include "ext/a.sgs", "a.sgs";
sys_backtrace [function]
sys_backtrace( bool as_string = false )
returns the call stack function/line/file list, either as array of dicts, or as a string, formatted exactly like in error messages (via sgs_PushErrorInfo)
- in the dict, there are three keys:
- func (string)
- line (null/int)
- file (string)
errprint( sys_backtrace( true ) ); // print backtrace to stderr
println( sys_backtrace().last.func ); // print name of current function
sys_msg [function]
sys_msg( int code, string message )
passes a message to the internal messaging system (one that's commonly used to report errors and warnings)
Different codes can be handled differently by the system. By default, SGS_ERROR code will stop execution and return to C code as soon as possible.
code
is the code to use to pass the message (ex. SGS_INFO, SGS_WARNING, SGS_ERROR)
INFO [function]
INFO( string message )
passes a message to the internal messaging system
- the name of this function is written in all caps to avoid shadowing by a common variable name
- works exactly like
sys_msg( SGS_INFO, message )
WARNING [function]
WARNING( string message )
passes a message to the internal messaging system
- the name of this function is written in all caps for consistency with the other two
- works exactly like
sys_msg( SGS_INFO, message )
ERROR [function]
ERROR( string message )
passes a message to the internal messaging system
By default, SGS_ERROR code (the one this function uses internally) will stop execution and return to C code as soon as possible.
- the name of this function is written in all caps to avoid shadowing by a common variable name
- works exactly like
sys_msg( SGS_INFO, message )
sys_abort [function]
sys_abort()
stops execution and returns to C code as soon as possible
- this function is equivalent to sgs_Abort in the C API
sys_abort();
print( 5 ); // this line is not reached
app_abort [function]
app_abort()
calls the abort() function of the C standard library (crashes the application)
app_exit [function]
app_exit( code = 0 )
calls the exit() function of the C standard library (exits the application)
sys_replevel [function]
sys_replevel([ level ])
returns the current reported error level and optionally sets a new one
The effects of this function are not reverted automatically at any moment (unless implemented manually with hooks).
old_level = sys_replevel( SGS_ERROR ); // report only errors or worse
magic = calculate_magic(); // any warnings are never processed at this point
sys_replevel( old_level ); // restore the old reported level
sys_stat [function]
sys_stat( code )
prints info about virtual machine state, everything is implementation-defined
- accepted codes are the same as for sgs_Stat, which this function is equivalent to
sys_stat( 11 ); // dumps all globals
errno [function]
errno( as_string = false )
returns the last relevant error number for the C standard library, as an integer or a string if as_string
is set
data = io_file_read( "doesnotexist" ); // file that does not exist
print errno(); // prints 2
print errno(true); // prints "No such file or directory" on Windows
errno_string [function]
errno_string( int code )
returns the error string for the given code
- errno_string(errno()) is equivalent to errno(true)
print errno_string(2); // prints "No such file or directory" on Windows
errno_value [function]
errno_value( string key )
returns the number for the error key (for "ENOENT" it would return 2)
- this function might be a bit slow considering that it currently does not use any extended lookup systems, such as hash tables
data = io_file_read( "doesnotexist" );
if( errno() == error_string("ENOENT") )
println( "file does not exist" );
dumpvar_ext [function]
dumpvar_ext( var, int depth = 5 )
similar to printvar_ext() but returns the dump instead of printing it
- this function is equivalent to sgs_DumpVar in the C API
sys_error( SGS_INFO, "Extended variable info:\n" $ dumpvar(data) );
dumpvar [function]
dumpvar( ... )
similar to printvar() but returns the dumps, concatenated, instead of printing them
gc_collect [function]
gc_collect()
runs the garbage collector on the virtual machine, waiting until it has finished
- returns the reduction in objects or false on failure
a = [];
a.push(a); // creates a circular dependency
a = null; // a is not actually freed
gc_collect(); // a is freed now
serialize [function]
serialize( var )
converts the variable to a byte buffer (string), containing the serialized data that can be recreated with unserialize() or returns null and emits a warning on failure
- C functions and objects without OP_SERIALIZE implemented cannot be serialized
data = serialize({ name = "A", info = "B" });
print data; // prints random-looking, yet deterministic garbage
print unserialize(data); // prints {name=A,info=B}
unserialize [function]
unserialize( string data[, array|dict funcs ])
recreates a variable from the buffer with serialized data or returns null and emits a warning on failure
- this function will internally call global object creation functions specified in the data, so they must be defined and the state could change in the process
- the list of allowed functions can be optionally specified in the second parameter
- if array is passed, all functions with the specified names are loaded from global environment
- if dict is passed, it is expected to be a map to be set as the temporary global environment
- for more info on serialization in SGScript, refer to Serialization in SGScript
data = serialize({ name = "A", info = "B" });
print data; // prints random-looking, yet deterministic garbage
print unserialize(data); // prints {name=A,info=B}
SGS_*** [constants]
SGS_INFO, SGS_WARNING, SGS_ERROR
defined to the values of the C macros, respectively 100, 200 and 300
VT_*** [constants]
VT_NULL, VT_BOOL, VT_INT, VT_REAL, VT_STRING, VT_FUNC, VT_CFUNC, VT_OBJECT, VT_PTR
these constants are defined to the values of the C macros (with the prefix "SGS_VT_" in C) and can be compared with the values returned in typeid()
RAND_MAX [constant]
RAND_MAX
the maximum number that can be returned by rand()
_G [superglobal]
A hard-coded global value that points to the global dictionary. Can be used to access non-identifier globals and change the global dictionary.
_G["$diff"] = 5; // no way to access this via usual globals
_G = {}; // global value dictionary is changed, previous functions are lost unless stored somewhere
array [object]
- methods
- read-only properties
- [int] size
- [int] capacity
- [var] first (valid if array is not empty, otherwise a warning is thrown and 'null' is returned)
- [var] last (similar to 'first')
- other features:
- read/write integer index
- full content dump
- tostring = quick content dump
- tobool = size != 0
- iterator
- cloning
- serialization
- GC-safe
array.push [method]
array.push( ... )
appends the variables passed to the end of array in the same order, returns the array for chaining
a = [ 5 ];
a.push( 6, 7 ).push( 8 ); // a = [5,6,7,8]
array.pop [method]
array.pop()
removes one item from the end of array or emits a warning if there are no items in the array, returns the removed item
a = [ 5 ];
a.pop(); // array is empty now
a.pop(); // warning: "array is empty, cannot pop"
array.shift [method]
array.shift()
removes one item from the beginning of array or emits a warning if there are no items in the array, returns the removed item
a = [ 5, 6 ];
a.shift(); // a = [6], returned 5
array.unshift [method]
array.unshift( ... )
prepends the variables passed to the beginning of array in the same order, returns the array for chaining
a = [ 5 ];
a.unshift( 6, 7 ); // a = [6,7,5] now
array.insert [method]
array.insert( int pos, ... )
inserts the variables passed (all arguments after first) to the position specified in the array or emits a warning on failure (index out of bounds), returns the array for chaining
pos
accepts both positive and negative values, the meaning is "which value to insert before"
- negative values are converted to positive ones by adding (<size> + 1) to them
- beginning of array can be inserted to using position 0 or (- <size> - 1)
- end of array can be inserted to using position <size> or -1
a = [ 5, 7 ];
a.insert( 1, 6 ); // inserts 6 at position 1 (before item with index 1)
a.insert( -1, 8 ); // appends to the end of array, a = [5,6,7,8] now
array.erase [method]
array.erase( int[, int] )
erases item or a range of items from the array, depending on the arguments passed or emits a warning on failure, returns the array for chaining
- both arguments have same index processing rules as array.insert(), but with one difference - if both arguments are passed, after resolving (converting negative indices to positive ones, if there are any), first must be smaller than second
a = [ 5, 6, 7, 8 ];
a.erase( 1, 2 ); // erases all items between position 1 and 2, including; gives a = [5,8]
a.erase( 0 ); // a = [8]
array.part [method]
array.part( int from[, int max ] )
returns a new array starting from index from
, with the max. size max
- if
from
is negative, it is subtracted from the end of array
max
cannot be negative, everything else is allowed
a = [ 5, 6, 7, 8 ];
a.part( 1, 2 ); // returns [6,7]
a.part( -5, 2 ); // returns [5]
a.part( 3 ); // returns [8]
array.clear [method]
array.clear()
erases all items from the array, returns the array for chaining
a = [ 1, "asd", 8 ];
a.clear(); // a = []
array.reverse [method]
array.reverse()
reverses the order of items in the original array, returns the original array for chaining
a = [ 1, 2, 3 ];
b = a;
a.reverse(); // a = [3,2,1]
print( b ); // prints [3,2,1]
array.resize [method]
array.resize( int size )
changes the size of the array, returns the array for chaining
size
must be larger than or equal to 0
- if previous size was less than passed to the method, null variables are appended
- if previous size was more than passed to the method, items are popped from the end of the array
- if size was not changed, nothing else will change
a = [ 5, 6, 7 ];
a.resize( 5 ); // a = [5,6,7,null,null]
a.resize( 2 ); // a = [5,6]
array.reserve [method]
array.reserve( int capacity )
reserves the space for the requested number of elements in the array, returns the array for chaining
capacity
must be larger than or equal to 0
- if previous capacity was less than passed to the method, capacity will be increased to the requested amount
- if previous capacity was more than or equal to what was passed to the method, nothing will change
a = [ 5, 6, 7 ];
a.capacity( 1 ); // nothing happens
a.capacity( 5 ); // a.capacity = 5 and two variable additions can now happen without reallocations
array.sort [method]
array.sort([ bool reverse ])
sorts the array using the sgs_Compare C API function for comparisons, returns the array for chaining
- if
reverse
is true, array is sorted in the reverse order
a = [ 6, 8, 7, 5 ];
a.sort(); // a = [5,6,7,8]
array.sort_custom [method]
array.sort_custom( callable[, bool reverse ] )
sorts the array using the callable for comparisons, returns the array for chaining
This function is considerably slower than array.sort or array.sort_mapped so prefer those if performance matters.
- callable must return a number, specifying the relative order of the two passed arguments: less than 0 if first variable should be placed before second, greater than 0 if first variable should be placed after second, or 0 if it doesn't matter
- if
reverse
is true, array is sorted in the reverse order
a = [ 6, 8, 7, 5 ];
// this code will sort numbers into odd/even ones and in ascending order
a.sort_custom( function(a,b){return a-b+(b%2-a%2)*1000; } ); // a = [5,7,6,8]
array.sort_mapped [method]
array.sort_mapped( array map[, bool reverse ] );
sorts the array by sorting the passed array and applying the index map to the first one, returns the array for chaining
- both arrays must have the same size, otherwise a warning is emitted
- all variables in the mapping array are interpreted as 'real' values
- if
reverse
is true, array is sorted in the reverse order
a = [ 5, 6, 7, 8 ];
b = [ 3, 1, 4, 2 ];
a.sort_mapped( b ); // a = [6,8,5,7]
array.find [method]
array.find( var item[, bool strict[, int from ]] )
attempts to find item
in array, starting from 0 or the index passed with from
, if it exists, using basic or strict equality comparisons (depending on strict
), returning the index or 'null' if item was not found
- if strict comparisons are enabled, variable types are also checked for equality
a = [ 5, 6, 7, 8 ];
a.find( "7" ); // returns 2
a.find( "7", true ); // returns null
array.remove [method]
array.remove( var item[, bool strict[, bool all[, int from ]]] )
attepts to find and remove first or all item
variables in array (depending on all
), according to the rules specified in array.find(), returning the number of removed items
a = [ 5, 2, 6, 7, 8, 2 ];
a.remove( "7" ); // returns 1; a = [5,2,6,8,2]
a.remove( "6", true ); // returns 0; a remains unchanged
a.remove( 2, false, true ); // returns 2; a = [5,6,8]
array.unique [method]
array.unique( bool strconv = false )
returns an array without duplicates, where a duplicate is a strictly equal variable or a string conversion match
- if
strconv
is true, items are converted to strings before comparison
a = [ 5, 3, 2, 3, 2, "3" ];
a.unique(); // returns [5,3,2,"3"]
a.unique( true ); // returns [5,3,2]
array.random [method]
array.random( int num )
return num
randomly chosen items from the array
- to retrieve a part of the array in random order without duplicates, array.shuffle can be used
- items after RAND_MAX will currently not be returned
array.shuffle [method]
array.shuffle()
change the order of items in the array
dict [object]
- features:
- read/write string index
- read/write string properties and integer index-via-property
- full content dump
- tostring = quick content dump
- tobool = size != 0
- iterator
- cloning
- serialization
- GC-safe
- type identification (returns the string "dict")
map [object]
- features:
- read/write index
- read/write properties
- full content dump
- tostring = quick content dump
- tobool = size != 0
- iterator
- cloning
- serialization
- GC-safe
- type identification (returns the string "map")
class [object]
- read/write properties
- other features
- read/write pass-through index
- read/write pass-through properties (except string "_super")
- full content dump
- tobool = ENOTSUP, overridable via "__tobool"
- toint = ENOTSUP, overridable via "__toint"
- toreal = ENOTSUP, overridable via "__toreal"
- tostring = "class", overridable via "__tostring"
- cloning, overridable via "__clone"
- type identification (returns the string "class", overridable via "__typeof")
- overridable arithmetic/comparison operations
- overridable object call
- serialization
- GC-safe
ALL SGScript core functions (A-Z)
Formatting library ("fmt")
This library includes functions and objects for parsing binary and text buffers.
Functions:
- fmt_pack - pack variables into a byte buffer, according to the format string
- fmt_unpack - unpack byte buffer to an array of variables, according to the format string
- fmt_pack_count - returns the number of items found in a packing format string
- fmt_pack_size - returns the number of bytes found in a packing format string
- fmt_base64_encode - encodes a byte buffer in base64 character buffer (A-Za-z0-9+/)
- fmt_base64_decode - decodes a base64 character buffer (A-Za-z0-9+/) to a byte buffer
- fmt_text - formats specified variables according to the format string
- fmt_parser - creates a text parser object with the specified stream reading function
- fmt_string_parser - creates a text parser object that reads from the specified string
- fmt_file_parser - creates a text parser object that reads from the specified file
- fmt_charcc - checks if a character is in the character class
Objects and their methods:
- fmt_parser - formatted text string-parsing object
- read - read the specified number of characters from the stream
- getchar - read one character from the stream
- readcc - read characters while they match the specified class
- skipcc - skip characters while they match the specified class
- read_real - read with the real value character class, optionally return real
- read_int - read with the integer value character class, optionally return integer
- read_binary_int - read with the binary integer character class, optionally -return integer
- read_octal_int - read with the octal integer character class, optionally return -integer
- read_decimal_int - read with the decimal integer character class, optionally -return integer
- read_hex_int - read with the hexadecimal integer character class, optionally return -integer
- check - check for presence of a string in stream
fmt_pack [function]
fmt_pack( string fmt, ... )
packs the given arguments using the format fmt
and returns the byte buffer or returns null and emits a warning on failure
- the format: character command list
- 0-9: add a digit to multiplier
- =/</>/@: "=" sets host byte order, "<" - little endian byte order, ">" - big endian, "@" - inverted
- +/-: "+" - unsigned integers, "-" - signed integers
- c/w/l/q/p: integers (c - char, 1 byte, w - word, 2 bytes, l - long, 4 bytes, q - quad-word, 8 bytes, p - pointer/size, platform-specific size of 4/8 bytes, usually)
- f/d: floating-point numbers: "f" - single precision, "d" - double precision
- s: string, multiplier sets length instead of count, as with other items
- x: padding byte (does not get read or written, can be used to advance the pointer)
- space/tab/CR/LF: invisible to the parser
- everything else resets multiplier, does nothing
- sign modifiers do nothing in fmt_pack, refer to fmt_unpack() for their usage info
printvar( fmt_pack( "3cf", 0, 1, 2, 3 ) ); // prints 'string [7] "\x00\x01\x02\x00\x00@@"'
fmt_unpack [function]
fmt_unpack( string fmt, string data )
unpacks the byte buffer data
using the format fmt
, returns unpacked items (possibly in an array)
- if '#' can be found in the format string, all data is returned in, otherwise
- unpacks c/w/l/q/p to integers, f/d to floats, s to strings
- if signed numbers are expected (as set by the "-" modifier), the sign bit of the expected type is extended to the end of the native integer type, this makes the loaded integer signed
- refer to fmt_pack() for more info about the format
print fmt_unpack( "3ld", fmt_pack( "3ld", 0, 1, 2, 3 ) ); // prints [0,1,2,3]
fmt_pack_count [function]
fmt_pack_count( string fmt )
calculates the number of items to be expected in an unpacked array / required to make a successful fmt_pack call
- refer to fmt_pack() for more info about the format
print fmt_pack_count( "3ld" ); // prints 4
fmt_pack_size [function]
fmt_pack_size( string fmt )
calculates the number of bytes generated by a successful fmt_pack call / required to successfully unpack data using the given format
- refer to fmt_pack() for more info about the format
print fmt_pack_size( "3ld" ); // prints 20
fmt_base64_encode [function]
fmt_base64_encode( string data )
encodes data to produce base64 text data
- encoding is done using the following table (shortened): "A-Za-z0-9+/"
print fmt_base64_encode( "hello world" ); // prints "aGVsbG8gd29ybGQ="
fmt_base64_decode [function]
fmt_base64_decode( string b64text )
decodes base64 text data
fmt_base64_decode( fmt_base64_encode( "hello world" ) ) == "hello world" // returns true
fmt_text [function]
fmt_text( [int prealloc,] string text, ... )
parses all format specifiers in text
and returns the result
see string_format if you need position (argument index) specifications in the format string
prealloc
specifies number of bytes to be preallocated on the buffer to avoid continuous reallocations during string generation
- the general format of a format specifier is as follows: {fmt[size][.prec][r][p<char>]}
- fmt: one-character output type (b-binary, o-octal, d-decimal, x/X-hexadecimal, f-floating-point, g/G-compact floating-point, e/E-scientific floating-point, s-valid string, c-always converted to string)
- size: minimum number of characters to print
- prec: precision of floating-point variables, string length limit
- r: add "r" to right-pad (left-justify)
- p<char>: add "p" and any character to set that character as the padding character (default: space/0x20)
- if anything unexpected happens, this function will emit a warning and put "#error#" in the place of a format specifier
print fmt_text( "{d} -> {x}", 1337, 1337 ); // prints "1337 -> 539"
print fmt_text( "null: {d}, {s}, {c}", null, null, null ); // prints "null: #error#, #error#, null" and emits two warnings for item 1 and item 2
print fmt_text( "pi: {f10.10r} {g10r} {E10r}", M_PI, M_PI, M_PI ); // "pi: 3.1415926536 3.14159 3.141593E+000"
fmt_parser [function]
fmt_parser( callable[, buffersize ] )
creates a fmt_parser object, connected to the callable
- the callable is a function that returns at most the number of bytes requested from the stream
- if previous request reached end, subsequent requests must return 'null'
f = io_file( "test.txt", FILE_READ );
// usually it is easier to use @fmt_file_parser instead of the next line of code
p = fmt_parser( function( num ) use( file ){ if( file.eof() ) return null; return file.read( num ); } );
fmt_string_parser [function]
fmt_string_parser( string, offset = 0[, buffersize ] )
creates a fmt_parser object, connected to a string reader object, initialized to the given offset and buffer size
p = fmt_string_parser( "this is a test" );
p.readcc( "a-z" ); // returns "this"
fmt_file_parser [function]
fmt_file_parser( file[, buffersize ] )
creates a fmt_parser object, connected to a file reader object, initialized to the given buffer size
p = fmt_file_parser( io_file( "something.txt", FILE_READ ) );
p.readcc( "a-z" ); // returns something
fmt_charcc [function]
fmt_charcc( string char, string class )
checks if the first character of string char
is included in the character class class
- character class is a regex-like list of specific symbols and ranges (its low and high symbols separated by "-"), optionally prepended by "^" that inverts the scope of the class
fmt_charcc( ".", "a-zA-Z0-9" ); // returns false
fmt_charcc( "x", "a-zA-Z0-9" ); // returns true
fmt_parser [object]
- methods
- read-only properties
- [bool] at_end
- [bool] stream_offset
- other features:
fmt_parser.read [method]
fmt_parser.read( int num )
reads at most num
bytes from stream and returns them as string
- if 0 bytes are returned, it's quite safe to assume that the function has reached the end of file but check the at_end property to be sure
- may return null and emit a warning on unexpected read errors
stream = fmt_string_parser( "action" );
stream.read( 5 ); // returns "actio"
fmt_parser.getchar [method]
fmt_parser.getchar( bool peek = false, bool as_int = false )
returns a character from stream
- if
peek
is true, stream is not advanced (next read operation will also work on the same character)
- if
as_int
is true, character is returned as integer (as one-character string otherwise)
- may return null and emit a warning on unexpected read errors
stream = fmt_string_parser( "action" );
stream.read( true ); // returns "a"
stream.read( true, true ); // returns 97
stream.read(); // returns "a"
stream.read(); // returns "c"
fmt_parser.readcc [method]
fmt_parser.readcc( string class, int num = 2^31-1 (0x7fffffff) )
reads and returns at most num
bytes that match the character class class
- returns null and emits a warning if the class is empty/only contains the inversion symbol "^"
- may return null and emit a warning on unexpected read errors
stream = fmt_string_parser( "what is this" );
stream.readcc( "a-z" ); // returns "what"
stream.readcc( "^a-z" ); // returns " "
fmt_parser.skipcc [method]
fmt_parser.skipcc( string class, int num = 2^31-1 (0x7fffffff) )
skips at most num
bytes that match the character class class
and returns the number of bytes skipped
- returns null and emits a warning if the class is empty/only contains the inversion symbol "^"
- may return null and emit a warning on unexpected read errors
stream = fmt_string_parser( "what is this" );
stream.skipcc( "a-z" ); // returns 4
stream.skipcc( "^a-z" ); // returns 1
fmt_parser.read_real [method]
fmt_parser.read_real( bool as_real = true )
returns characters read with the character class "-+0-9.eE", optionally returned as a real value
fmt_parser.read_int [method]
fmt_parser.read_int( bool as_int = true )
returns characters read with the character class "-+0-9A-Fa-fxob", optionally returned as an int value
fmt_parser.read_binary_int [method]
fmt_parser.read_binary_int( bool as_int = true )
returns characters read with the character class "0-1", optionally returned as an int value
fmt_parser.read_octal_int [method]
fmt_parser.read_octal_int( bool as_int = true )
returns characters read with the character class "0-7", optionally returned as an int value
fmt_parser.read_decimal_int [method]
fmt_parser.read_decimal_int( bool as_int = true )
returns characters read with the character class "-+0-9", optionally returned as an int value
fmt_parser.read_hex_int [method]
fmt_parser.read_hex_int( bool as_int = true )
returns characters read with the character class "0-9a-fA-F", optionally returned as an int value
fmt_parser.check [method]
fmt_parser.check( string str, bool ci = false, bool partial = false )
returns whether the specified string was found at the current position
ci
makes matching case-insensitive
- if
partial
is true, function returns the number of characters successfully matched instead of whether everything has been matched
ALL SGScript formatting functions (A-Z)
I/O library ("io")
This library contains the functions necessary to work with the file system (files and directories).
Functions:
Objects and their methods:
- io_file - file object
- open - open a file
- close - close the currently open file (if any)
- read - read from the open file
- write - write to the open file
- seek - change read/write position in file
- flush - flush the write buffer
- setbuf - change the size and flush trigger of the write buffer or disables it
- io_dir - directory iterator object, for use in "foreach"
Constants:
io_setcwd [function]
io_setcwd( string cwd )
sets the current working directory, returns bool/sets errno
io_getcwd [function]
io_getcwd()
returns the current working directory or null, if for some reason an error occured
- in case of failure, function will set errno
io_getexecpath [function]
io_getexecpath()
returns the path of the executable file the script is executed in
- in case of failure, function will set errno
io_rename [function]
io_rename( string path, string newpath )
attempts to rename the file, returns bool/sets errno
- wraps the C library function rename
- to avoid moving the file/directory, make sure both paths are of the same origin
io_file_exists [function]
io_file_exists( string file )
checks if file exists and is accessible by the process at the moment, returns true on success, false otherwise
- uses the C library functions fopen/fclose
io_dir_exists [function]
io_dir_exists( string dir )
checks if directory exists and is accessible by the process at the moment, returns true on success, false otherwise
- uses the C library functions opendir,closedir where supported properly, Windows API Find*** functions otherwise
io_stat [function]
io_stat( string fsitem )
returns info about the file system item fsitem
, as dict
- the returned object contains the following properties:
- atime: last access time
- ctime: creation time
- mtime: last modification time
- type: enum (one of FST_DIR/FST_FILE/FST_UNKNOWN)
- size: size of item
- uses the C library function stat/_stat
io_dir_create [function]
io_dir_create( string path, int mode = 0o777 )
attempts to create a directory at the specified path, with the specified access mode mode
, returns bool/sets errno
mode
is ignored on Windows
- uses the C library function mkdir/_mkdir
io_dir_delete [function]
io_dir_delete( string path )
attempts to delete a directory at the specified path, returns bool/sets errno
- uses the C library function rmdir/_rmdir
io_file_delete [function]
io_file_delete( string path )
attempts to delete a file at the specified path, returns bool/sets errno
- uses the C library function remove
io_file_write [function]
io_file_write( string path, string data )
writes the byte buffer data
to the file pointed to by path
, returns bool/sets errno
io_file_read [function]
io_file_read( string path )
reads the byte buffer from file at path
, returns buffer as string or null/sets errno
io_file [object]
- methods
- read-only properties
- [int] offset
- [int] size
- [bool] error
- [bool] eof
- other features:
- tobool = returns whether file is open or not
- GC-safe
io_file.open [method]
io_file.open( string name, int mode )
closes the previously open file if any, opens the file name
for operation mode mode
, returns bool/sets errno
mode
must be one of FILE_READ, FILE_WRITE or FILE_READ|FILE_WRITE
- file is always opened in binary mode
f = io_file();
f.open( "file" ); // returns true or false, sets errno accordingly
io_file.close [method]
io_file.close()
closes the previously open file, if any, returns whether the file was open or not
f = io_file( "file.txt" );
f.close(); // returns true if the file existed
f.close(); // returns false
io_file.read [method]
io_file.read( int num )
reads and returns at most num
bytes from file, sets errno
io_file.write [method]
io_file.write( string data )
writes the byte buffer data
to the file, sets errno
io_file.seek [method]
io_file.seek( int off, int mode )
sets the offset in file, returns bool/sets errno
mode
must be one of SEEK_SET (sets as-is), SEEK_CUR (sets relative to current), SEEK_END (sets relative to end)
io_file.flush [method]
io_file.flush()
flushes a buffered file, returns bool
io_file.setbuf [method]
io_file.setbuf( int size )
sets the size of file buffer (0 to disable buffering), returns bool
- buffering allows to avoid committing each write immediately to disk, resulting in a performance gain, however it may introduce issues if application is expected to fail at any moment, resulting in some data not being written in such cases
io_file [function]
io_file([ string name, int mode ])
creates and returns a file, optionally allowing to open it on creation
- see io_file.open() for more info on opening the file
io_dir (directory_iterator) [object]
- features:
- tostring = "directory_iterator"
- iterator interface (key = whether real item, value = item name)
- real items are all except "." and ".."
- returns self as iterator
- GC-safe
- type identification (returns the string "directory_iterator")
io_dir [function]
io_dir( string dir )
creates a directory iterator for the directory dir
, sets errno, returns null and emits a warning on failure
FILE_*** [constants]
FILE_READ, FILE_WRITE
SEEK_*** [constants]
SEEK_SET, SEEK_CUR, SEEK_END
mode constants for io_file.seek
FST_*** [constants]
FST_UNKNOWN, FST_FILE, FST_DIR
file system item type constants for io_stat
ALL SGScript I/O functions (A-Z)
Math library ("math")
This library contains the basic math functions for processing real values.
Functions:
- abs - returns the absolute value of x
- floor - returns rounded-down value of x
- ceil - returns the rounded-up value of x
- round - returns the rounded-to-nearest-integer value of x
- pow - returns x to the power of y
- sqrt - returns a square root of x
- log - returns the logarithm (power) of x for base y
- sin - returns the sine of x
- cos - returns the cosine of x
- tan - returns the tangent of x
- asin - returns arcsine (angle for sine value) of x
- acos - returns arccosine (angle for cosine value) of x
- atan - returns arctangent (angle for tangent value) of x
- atan2 - returns arctangent of x and y, using both values to extend the range of returned value
- deg2rad - returns x degrees as radians
- rad2deg - returns x radians as degrees
Constants:
- M_*** - mathematical constants
abs [function]
abs( x )
returns the absolute value of x
, as real
abs( 2.2 ); // real (2.2)
abs( -3.1 ); // real (3.1)
floor [function]
floor( x )
returns the largest integer that is not bigger than x
, as real
floor( 3.4 ); // real (3)
floor( 3.8 ); // real (3)
floor( 4.2 ); // real (4)
floor( -3.1 ); // real (-4)
ceil [function]
ceil( x )
returns the smallest integer that is not smaller than x
, as real
ceil( 3.4 ); // real (4)
ceil( 3.8 ); // real (4)
ceil( 4.2 ); // real (5)
ceil( -3.1 ); // real (-3)
round [function]
round( x )
returns the closest integer to x
, as real
round( 3.4 ); // real (3)
round( 3.8 ); // real (4)
round( 4.2 ); // real (4)
round( -3.1 ); // real (-3)
pow [function]
pow( x, y )
returns x
raised to the power y
, as real
- If base (
x
) is negative and exponent (y
) is not an integral value, or if base is zero and exponent is negative, function returns null
and emits a warning message.
pow( 2, 5 ); // real (32)
pow( 9, 0.5 ); // real (3)
pow( -1, 0.5 ); // null; Warning: pow(): mathematical error
sqrt [function]
sqrt( x )
returns the square root of x
, as real
- If
x
is negative, function returns null
and emits a warning message.
sqrt( 16 ); // real (4)
sqrt( -1 ); // null; Warning: sqrt(): mathematical error
log [function]
log( x, y )
returns the base-`y` logarithm of x
, as real
- If
x <= 0
or b <= 0
or b = 1
, function returns null
and emits a warning message.
log( 9, 3 ); // real (2)
log( -1, 3 ); // .. or ..
log( 3, 0 ); // .. or ..
log( 3, 1 ); // null; Warning: log(): mathematical error
sin [function]
sin( x )
returns the sine of angle x
in radians, as real
sin( 0 ); // real (0)
sin( M_PI / 2 ); // real (1)
sin( M_PI / 4 ); // real (0.707107)
cos [function]
cos( x )
returns the cosine of angle x
in radians, as real
sin( 0 ); // real (1)
sin( M_PI ); // real (-1)
sin( M_PI / 4 ); // real (0.707107)
tan [function]
tan( x )
returns the tangent of angle x
in radians, as real
tan( 0 ); // real (0)
tan( 1 ); // real (1.55741)
tan( M_PI / 4 ); // real (1)
asin [function]
asin( x )
returns the arcsine of x
(angle in radians), as real
- If
x
is outside the [-1,1] range, function returns null
and emits a warning message
asin( -1 ); // real (-1.5708)
asin( 0 ); // real (0)
asin( 2 ); // null; Warning: asin(): mathematical error
acos [function]
acos( x )
returns the arccosine of x
(angle in radians), as real
- If
x
is outside the [-1,1] range, function returns null
and emits a warning message
acos( -1 ); // real (3.14159)
acos( 0 ); // real (1.5708)
acos( 2 ); // null; Warning: acos(): mathematical error
atan [function]
atan( x )
returns the arctangent of x
(angle in radians), as real
atan( 0 ); // real (0)
atan( 1 ); // real (0.785398)
atan( 9999999 ); // real (1.5708)
atan2 [function]
atan2( y, x )
returns the extended arctangent of y/x (angle in radians), as real
- Signs of
x
and y
are used to determine the quadrant, thus y
is expected to be the sine of the angle to be returned (the y
coordinate of a point) and x
- the cosine (the x
coordinate).
Due to the common requirement to use this function to determine the angle between two somewhat random points (usually from a simulation), it will not emit a warning when both arguments are 0 - it will return 0 instead.
atan2( 0, 1 ); // real (0)
atan2( 1, 0 ); // real (1.5708)
atan2( -1, -1 ); // real (-2.35619)
atan2( 0, 0 ); // real (0)
deg2rad [function]
deg2rad( x )
returns angle, converted from degrees to radians, as real
deg2rad( 0 ); // real (0)
deg2rad( 180 ); // real (3.14159)
deg2rad( -90 ); // real (-1.5708)
rad2deg [function]
rad2deg( x )
returns angle, converted from radians to degrees, as real
rad2deg( 0 ); // real (0)
rad2deg( M_PI ); // real (180)
rad2deg( -M_PI / 2 ); // real (-90)
M_*** [constants]
M_PI
the ratio of circumference of a circle to its diameter (pi)
- the value of this constant is
3.14159265358979323846
M_E
the natural logarithmic base (e)
- the value of this constant is
2.7182818284590452354
ALL SGScript math functions (A-Z)
OS library ("os")
- environment variables
- time and date
- locale / regional settings
Functions:
Constants:
os_gettype [function]
os_gettype()
returns the name of the closest known match for the operating system type, defined at library compile time
- the function can detect and return the following OSes at the moment (with the preprocessor define in braces):
- "Windows" (_WIN32/__WIN32__/__WINDOWS__)
- "Mac OS X" (__APPLE__)
- "Android" (__ANDROID__)
- "Linux" (__linux/__linux__)
- "Unix" (__unix/__unix__)
- "POSIX" (__posix)
- "Unknown" (..any other)
os_command [function]
os_command( string cmd )
passes a command to the OS command processor, returns the integer return value
this function can be extremely unsafe in multithreaded/incontrollable environments due to the completely undefined outcome of the call
- uses the C library function 'system'
os_getenv [function]
os_getenv( string var )
returns the value for the environment variable var
or null, if there is no such value
os_putenv [function]
os_putenv( string cmd )
sets the value for the environment variable specified in command cmd
, returns success as bool
cmd
has the format "<name>=<value>"
os_time [function]
os_time( real tz = <local> )
returns the time in seconds, as integer, optionally from a different time zone tz
os_get_timezone [function]
os_get_timezone( bool as_string = false )
returns the time zone set in the operating system, optionally as string in the format "(+/-)HH:MM"
os_date_string [function]
os_date_string( string fmt, int time = os_time() )
returns the date/time string in the format fmt
, optionally for a different time time
- the following item specifiers are supported (*-local-specific):
- %a: abbreviated weekday name *
- %A: full weekday name *
- %b: abbreviated month name *
- %B: full month name *
- %c: full date/time *
- %x: full date *
- %X: full time *
- %Z: timezone name/abbreviation (could be an empty string) *
- %U: week number with first Sunday as the first day of week one *
- %W: week number with first Monday as the first day of week one *
- %C: year/100, as integer
- %d: zero-padded day of the month (01-31)
- %e: space-padded day of the month ( 1-31)
- %F: date, shortcut of "%Y-%m-%d"
- %H: hour in 24h format (00-23)
- %I: hour in 12h format (01-12)
- %j: day of the year (001-366)
- %m: month number (01-12)
- %M: minute (00-59)
- %p: AM or PM
- %R: hour/minute time, shortcut to %H:%M
- %s: second (00-61)
- %T: time, shortcut to %H:%M:%S
- %u: weekday with Sunday as 0
- %w: weekday with Monday as 1
- %y: 2-digit year (00-99)
- %Y: year
- %f: file-safe full time, shortcut to %Y-%m-%d_%H-%M-%S
- %t: the UNIX timestamp
- %%: prints "%"
- %<any other>: prints both characters
os_parse_time [function]
os_parse_time( int time = os_time() )
returns time
split into parts, as dict
- the returned dict contains the following properties (all are integers):
- year (1900-????)
- month (1-12)
- day (1-31)
- weekday (1-7)
- yearday (1-366)
- hours (0-23)
- minutes (0-59)
- seconds (0-61)
os_make_time [function]
os_make_time( int sec, int min = 0, int hour = 0, int mday = 0, int mon = 0, int year = 0 )
returns time as UNIX timestamp, generated from the arguments, using them as hints (under-/overflows may have some unexpected behavior)
os_get_locale [function]
os_get_locale( int which )
returns the currently set locale for the specified category
which
must be one of the LC_ constants
- the returned string is platform-specific
- wraps the C library function setlocale
os_set_locale [function]
os_set_locale( int which, string locale )
sets the locale for the specified category, returning whether the call was successful
which
must be one of the LC_ constants
- the available locale strings are platform-specific
- wraps the C library function setlocale
os_get_locale_format [function]
os_get_locale_format()
retrieve the formatting info of the currently set locale as a dict
- wraps the C library function localeconv
- the returned data is identical to pre-C99 format of struct lconv
os_locale_strcmp [function]
os_locale_strcmp( string a, string b )
compare two strings using locale to return correct sign for inequalities (good for language-correct sorting)
- expected encoding depends on the platform and the locale that is currently set
- wraps the C library function strcoll
LC_*** [constants]
These constants specify the categories for which locale can be changed.
- LC_ALL affects every locale-related function
- LC_COLLATE: os_locale_strcmp
- LC_MONETARY: os_get_locale_format
- LC_NUMERIC: os_get_locale_format
- LC_TIME: os_date_string
ALL SGScript OS functions (A-Z)
Regular expression library ("re")
This library includes regular expression match & replace functions.
Functions:
- re_match - check for first match in string for pattern
- re_match_all - check for all matches in string for pattern
- re_replace - replace all matches in string for pattern with the specified string
Constants:
re_match [function]
re_match( string str, string pattern, int flags = 0, int offset = 0 )
check for matches in string str
for pattern
, returning whether a match was found or details of the first match, as specified in flags
offset
specifies the character to start matching from, negative offset is subtracted from the end
flags
expect RE_RETURN_CAPTURED, RE_RETURN_OFFSETS or RE_RETURN_BOTH, which is a combination of the previous two
- if
flags
is one of the special values, function returns an array of captured ranges
- each entry is either a string (on RE_RETURN_CAPTURED) or an array of beginning and end offsets (at positions 0 and 1, respectively, on RE_RETURN_OFFSETS) or an array of a string and the beginning and end offsets (on RE_RETURN_BOTH)
- the first character in the pattern specifies a delimiter that separates the pattern from modifiers
- example pattern strings: "/^[a-z]+/mi", "#[a-z0-9_]+.*?#s"
- more info about the supported features and modifiers at https://github.com/snake5/sgregex
re_match_all [function]
re_match_all( string str, string pattern, int flags = 0, int offset = 0 )
check for matches in string str
for pattern
, returning the number of matches or details of all matches, as specified in flags
- similar to re_match, only difference is in the return value:
- if
flags
is one of the special values, function returns an array of matches where each match is an array of captured ranges
re_replace [function]
re_replace( string str, string pattern, string replacement )
find and replace all occurrences of pattern
in string str
with the replacement
string
- replacement string can contain backreferences in the forms "$[0-9]" or "\[0-9]" (in a string constant, a double backslash is required due to rules in SGScript)
- there can be up to 10 backreferences, 0-9, 0 being the whole match
RE_RETURN_*** [constants]
These constants are used in re_match / re_match_all to specify the format of the return value.
If none of these are specified (flags
= 0), only the success state is returned (true/false/match count).
- RE_RETURN_CAPTURED - return the captured string
- RE_RETURN_OFFSETS - return array of start/end offsets
- RE_RETURN_BOTH - return both the captured string and the start/end offsets in an array
ALL SGScript RegExp functions (A-Z)
String library ("string")
This library contains the string handling functions. In all functions, except the utf-8 ones, it is assumed that strings are byte buffers where each byte is one character. If correct indices are applied, many of them will work with multibyte strings.
Objects:
Functions:
- string_cut - extract a substring from a string from the specified beginning / end offsets
- string_part - extract a substring from a string from the specified offset and length
- string_reverse - reverse the order of bytes in a string
- string_pad - pad one or both sides of a string with a pattern string up to the specified length
- string_repeat - concatenate several copies of the specified string
- string_count - count occurences of a substring in a string
- string_find - find first substring in the string, optionally after the specified position
- string_find_rev - find a substring by walking the string backwards, optionally before the specified position
- string_replace - replace parts of string according to match / replacement strings or arrays
- string_translate - replace parts of string according to the provided match -> replacement mapping dict
- string_trim - trim one or both sides of string, removing the specified or default character set
- string_toupper - convert all ASCII lowercase characters into uppercase equivalents
- string_tolower - convert all ASCII uppercase characters into lowercase equivalents
- string_compare - compare strings as byte arrays
- string_implode - combine an array of strings, putting a separator string between each two consecutive strings
- string_explode - split string into parts, separated by the specified separator string
- string_charcode - get the character code (byte value, as integer) from the specified position in string
- string_frombytes - make a string from an array of integer values, interpreted as bytes
- string_utf8_decode - decode a UTF-8 string into an array of code points
- string_utf8_encode - encode an array of code points into a UTF-8 string
- string_utf8_offset - get byte offset of a specific character
- string_utf8_length - get UTF-8 length of string or its part
- string_utf8_iterator - create an iterator for UTF-8 code points in a string
- string_format - format variables according to the specified format string
Constants:
- STRING_NO_REV_INDEX - used by string_cut / string_part - disable handling of negative indices
- STRING_STRICT_RANGES - used by string_cut / string_part - disable handling of out-of-bounds indices
- STRING_TRIM_LEFT, STRING_TRIM_RIGHT - used by string_trim - specify sides to be trimmed
- STRING_PAD_LEFT, STRING_PAD_RIGHT - used by string_pad - specify sides to be padded
string_utf8_iterator [object]
- read/write properties:
- [int] offset - returns the point in string from which last character was retrieved, can set point in string from which next character will be retrieved
- read-only properties:
- [string] string - returns the string currently being iterated on
- other features:
- iterator (self)
- cloning
- serialization
- GC-safe
string_cut [function]
string_cut( string str, int from[, int to[, int flags]] )
returns a part of string str
, from
and to
being positions of the first and last character returned, respectively
- if
to
is not specified, to
is assumed to be the position of the last character in string str
- if
from
or to
are negative, they point to characters before the end of string (-1 being the last one)
- available values for
flags
:
STRING_NO_REV_INDEX
- emit warnings on negative indices, instead of handling them
STRING_STRICT_RANGES
- emit warnings on out of bounds from
/to
values instead of silently ignoring the outside characters
string_cut( "01234567", 3, 5 ); // string [3] "345"
string_part [function]
string_part( string str, int from[, int len[, int flags]] )
returns a part of string str
, starting at from
, at most len
characters
- if
len
is not specified, len
is assumed to be the number of characters between from
and the end of string str
- if
from
is negative, it points to characters before the end of string (-1 being the last one)
- if
len
is negative, the maximum length of returned string is the sum of len
and string str
length
- available values for
flags
:
STRING_NO_REV_INDEX
- emit warnings on negative indices, instead of handling them
STRING_STRICT_RANGES
- emit warnings on out of bounds from
/len
values instead of silently ignoring the outside characters
string_part( "01234567", 3, 3 ); // string [3] "345"
string_reverse [function]
string_reverse( string str )
returns str
with all the bytes in reversed order
This function will not work correctly with multibyte-encoded strings.
string_reverse( "noitca" ); // string [6] "action"
string_pad [function]
string_pad( string str, int tgtsize, string padstr = " ", int flags = STRING_PAD_RIGHT )
return the string str
, padded from template padstr
up to the size tgtsize
according to flags
- if
str
is longer than tgtsize
, it is returned without changes
- available values for
flags
:
STRING_PAD_LEFT
- pad the string at the left side
STRING_PAD_RIGHT
- pad the string at the right side
- if both flags are OR'ed together, the string
str
is centered
- at least one of the flags must be specified if the argument is passed for the function to work
string_pad( "padded", 10 ); // string [10] "padded "
string_pad( "center", 10, "_", STRING_PAD_LEFT | STRING_PAD_RIGHT ); // string [10] "__center__"
string_repeat [function]
string_repeat( string str, int count )
return the string str
, appended to itself `count`-1 times or an empty string if count
is equal to 0
count
must be greater than or equal to 0
string_repeat( "na", 6 ); // string [12] "nananananana"
string_repeat( "none", 0 ); // string [0] ""
string_count [function]
string_count( string str, string substr, bool overlap = false )
returns the number of substrings substr
found in string str
- if
overlap
is true, function does not skip substrings when they are found
string_count( "abababa", "aba" ); // int 2
string_count( "abababa", "aba", true ); // int 3
string_find [function]
string_find( string str, string substr, int offset = 0 )
returns the position of first found substring substr
in string str
, starting at offset
- if
substr
was not found, 'null' is returned
- if
offset
is less than 0, it specifies offset from the end
string_find( "what hat", "hat" ); // int 1
string_find( "what", "hat", 2 ); // null
string_find_rev [function]
string_find_rev( string str, string substr, int offset = 0 )
returns the position of last found substring substr
in string str
, starting at offset
- if
substr
was not found, 'null' is returned
- if
offset
is less than 0, it specifies offset from the end
string_find_rev( "what hat", "hat" ); // int 5
string_find_rev( "what", "hat", 2 ); // int 1
string_replace [function]
string_replace( string str, string from, string to )
string_replace( string str, array from, string to )
string_replace( string str, array from, array to )
replaces parts of string str
, specified in from
, to the respective values passed in to
- the respective replacement is picked by taking the substring index and performing modulo operation with the number of replacement strings
string_replace( "loaded %num files", "%num", 5 ); // string [14] "loaded 5 files"
string_replace( "abcd", ["a","b","c","d"], [1,2,3,4] ); // string [4] "1234"
string_replace( "1234", ["1","2","3","4"], ["x","y"] ); // string [4] "xyxy"
string_translate [function]
string_translate( string str, iterable repmap )
replaces parts of string str
, specified in the keys of repmap
, to the matching values of the same iterable
string_translate( "found %a files and %b folders", {"%a" = 5, "%b" = 17} ); // string [28] "found 5 files and 17 folders"
string_trim [function]
string_trim( string str, string chars = " \t\r\n", int flags = STRING_TRIM_LEFT | STRING_TRIM_RIGHT )
removes the specified characters from the specified sides of the string
- available values for
flags
:
STRING_TRIM_LEFT
- trim the string from the left side
STRING_TRIM_RIGHT
- trim the string from the right side
string_trim( " space " ); // string [5] "space"
string_trim( "..something!..", ".!", STRING_TRIM_RIGHT ); // string [11] "..something"
string_toupper [function]
string_toupper( string str )
converts all ASCII lowercase letter characters of the string to uppercase
string_toupper( "Test" ); // string [4] "TEST"
string_tolower [function]
string_tolower( string str )
converts all ASCII uppercase letter characters of the string to lowercase
string_toupper( "Test" ); // string [4] "test"
string_compare [function]
string_compare( string str1, string str2, int max = 0, int from = 0 )
compares the two strings or the specified portions of them
string_compare( "what", "whaT" ); // int 1
string_compare( "what", "whaT", 3 ); // int 0
string_compare( "file.txt", ".txt", 0, -4 ); // int 0
string_implode [function]
string_implode( array items, string sep )
concatenates the string representations of array items
values, putting a string sep
between each two
string_implode( ["one","two","three"], ", " ); // string [15] "one, two, three"
string_explode [function]
string_explode( string str, string sep )
splits the string str
into an array of substrings, separated by string sep
string_explode( "www.example.com", "." ); // ["www","example","com"]
string_explode( "x", "-" ); // ["x"]
string_explode( "/some//data", "/" ); // ["","some","","data"]
string_charcode [function]
string_charcode( string str, int offset = 0 )
returns the byte value / ASCII character code of the specified byte in the string
string_charcode( "Test" ); // int 84
string_charcode( "Test", 3 ); // int 116
string_frombytes [function]
string_frombytes( int byteval )
string_frombytes( array bytes )
returns a string, created from either one byte value (overload #1) or an array of byte values (overload #2)
- byte values must be in the range [0-255]
string_frombytes( 53 ); // string [1] "5"
string_frombytes([ 84, 101, 115, 116 ]); // string [4] "Test"
string_utf8_decode [function]
string_utf8_decode( string ustr )
returns an array of Unicode code points, decoded from the UTF-8 string ustr
- invalid byte sequences will add 0xFFFD to the array
string_utf8_decode( "pie" ); // [112,105,101]
string_utf8_decode( "код" ); // [1082,1086,1076]
string_utf8_decode( "標準" ); // [27161,28310]
string_utf8_encode [function]
string_utf8_encode( array cplist )
returns a UTF-8 string, composed from the Unicode code point list cplist
string_utf8_encode([ int cp0[, int cp1, ... ]])
returns a UTF-8 string, composed from the Unicode code point list passed in argument list
Without proper terminal software UTF-8 strings will not be displayed correctly (as is the case on Windows).
- invalid code points will add "\xEF\xBF\xBD" (0xFFFD code point as UTF-8) to the string
string_utf8_encode( [112,105,101] ); // string [3] "pie"
string_utf8_decode( [1082,1086,1076] ); // string [6] "код"
string_utf8_decode( [27161,28310] ); // string [6] "標準"
string_utf8_offset [function]
string_utf8_offset( string ustr, int charnum[, int byteoff ])
returns byte offset of character in UTF-8 string, optionally skipping the specified number of bytes
- valid character numbers are 0 to actual number of characters from specified byte offset
- valid byte offsets are 0 to ustr.length
string_utf8_offset( "標準", 2 ); // returns 6
string_utf8_length [function]
string_utf8_length( string ustr, int byteoff = 0[, int numbytes[, int flags ]])
returns length of UTF-8 string or the specified part of it
string_utf8_length( "標準", 3 ); // returns 1
string_utf8_iterator [function]
string_utf8_iterator( string ustr, int byteoff = 0 )
creates a UTF-8 code point iterator object
it = string_utf8_iterator( "標準" ); // returns string_utf8_iterator object
iter_advance( it ); // go to position 0
iter_getdata( it ); // returns 27161
string_format [function]
string_format( [int prealloc,] string text, ... )
parses all format specifiers in text
and returns the result
see fmt_text if you don't need the position (argument index) specifications
prealloc
specifies number of bytes to be preallocated on the buffer to avoid continuous reallocations during string generation
- the format specifier has the form {<id>:<specifier>} where "id" is the argument index to use and specifier is a fmt_text specifier
- argument indices to be used in specifiers start from 1
print string_format( "{1:d} -> {1:x}", 1337 ); // prints "1337 -> 539"
ALL SGScript string functions (A-Z)
Included tools
Executables
Extensions
Virtual Machine (sgsvm)
This is the default standalone environment for SGScript, useful for running scripts in a portable way.
Command line syntax
sgsvm [files|options]
sgsvm [options] -p|--program <srcname>[, <arguments>]
Options
-h
, --help
: print help text, displaying command line syntax
-v
, --version
: print version info
-s
, --separate
: restart the engine between scripts
-d
, --debug
: enable interactive debugging on errors
-p
, --program
: translate the following arguments into a SGS program call
--stats
: print VM stats after running the scripts
- prints number of allocations, frees, memory blocks and size, object count, GC state
--profile
: enable profiling by collecting call stack timings
--profile-ops
: enable low-level VM instruction profiling
--profile-mem
: enable memory usage profiling
Example usage
sgsvm -d -p appMain param=1
- run application appMain
with debugging, passing argument 'param=1'
sgsvm one.sgs two.sgs
- run file one.sgs
, followed by two.sgs
, in the same environment
Additional info
- Program mode defines global
argc
and argv
variables, generated from arguments after the flag.
- It is possible to execute multiple files, this is so that environment could be prepared by one file and used by another one.
- Profilers dump their data to standard output before freeing the engine (after end of each separately executed script or at the end of all scripts).
Compiler (sgsc)
This is the standalone script compiler and instruction listing generator for SGScript.
Command line syntax
sgsc [file|options]
Additional info
-h
: print help info
-c
: compile the file
-d
: dump bytecode to standard output
-o
: specify bytecode output file (default: remove .sgs on end, add .sgc)
Example usage
sgsc -c src.sgs
- compile src.sgs
to src.sgc
sgsc -d src.sgs
- compile src.sgs
, dump generated bytecode
Executable generator for Windows (sgsexe)
Utility to combine a single script with the virtual machine. After compilation, the executable passes all input arguments as-is as argc
and argv
to the script.
Command line syntax
sgsexe <output-file> <script-file>
Language test application (sgstest)
The application runs all test scripts in ./tests
directory. File handling rules are as follows:
- Ignore files with
!_
prefix.
- Require compilation success for tests with
s_
prefix.
- Require compilation failure for tests with
f_
prefix.
- If there is no prefix, require that the system does not crash.
- If a file name as
TF
in it, use the advanced testing framework.
- Files are sorted according to the logical order of testing: requirements grow with test file number:
- first sort by whether testing framework (TF) is required (files that don't need it go first);
- then sort by whether compilation success is required (files that do need it go first);
- finally, sort by whether compilation state is expected (files that do need it go first);
The sort order broken down:
- 1.
s_
tests without TF
- 2.
f_
tests without TF
- 3. tests without prefix and
TF
- 4.
s_
tests with TF
- 5.
f_
tests with TF
(none such tests exist because it would make no sense to have them)
- 6. tests without prefix but with
TF
The application sgstest
must be run from root, like so: bin/sgstest
. It generates two log files: ./tests-errors.log
and ./tests-output.log
.
API test application (sgsapitest)
This application tests the core programming interface. It generates two log files: ./apitests-errors.log
and ./apitests-output.log
.
C++ binding compiler test application (sgscppbctest)
This application tests the C++ programming interface that utilizes the binding compiler.
Lightweight C++ binding test application (sgscppbindtest)
This application tests the C++ programming interface that utilizes the lightweight binding extension.
Multithreading safety test application (mttest)
This application tests the SGScript engine's ability to work with more than one thread (different instances for each) at the same time.
Profiler
This is an engine profiler hook extension. It supports three processing modes.
Modes
- Function timing profiler: use SGS_PROF_FUNCTIME to initialize
- Instruction timing profiler: use SGS_PROF_OPTIME to initialize
- Memory usage profiler: use SGS_PROF_MEMUSAGE to initialize
Functions
- SGSBOOL sgs_ProfInit( SGS_CTX, SGS_PROF, int mode ) - initialize the profiler
- SGSBOOL sgs_ProfClose( SGS_PROF ) - free the profiler
- SGSBOOL sgs_ProfDump( SGS_PROF ) - dump the data
Usage example
sgs_Prof profiler; // keep this allocated while it is linked to engine
// initialize and attach the profiler
sgs_ProfInit( contextPtr, &profiler, [SGS_PROF_FUNCTIME|SGS_PROF_OPTIME|SGS_PROF_MEMUSAGE] );
// ...do things with the engine...
sgs_ProfDump( &profiler ); // dump the data (done through @sgs_Write* functions)
// free the profiler - must be done before freeing the engine
sgs_ProfClose( &profiler );
Interactive debugger
This is an engine debugging hook extension. It provides the opportunity to interactively introspect the engine state on each message (info/warning/error).
Functions
- int sgs_InitIDbg( SGS_CTX, SGS_IDBG ) - initialize the debugger
- int sgs_CloseIDbg( SGS_CTX, SGS_IDBG ) - free the debugger
Usage example
sgs_IDbg debugger; // keep this allocated while it is linked to engine
// initialize and attach the debugger
sgs_InitIDbg( contextPtr, &debugger );
// ...do things with the engine...
// free the debugger
sgs_CloseIDbg( contextPtr, &debugger );
Serialization in SGScript
In SGScript, serialization is conversion to a binary stream of a specific format. Serialization in the language API is done by calling the "serialize" function and deserialization is done with "unserialize". The C API has similar functions: sgs_Serialize / sgs_SerializeObject and sgs_Unserialize, respectively.
check the "Possible gotchas" part of this page if it is intended to trust the end user with access to serialized data
The format
- a list of operations
- each operation consists of a 'type' byte and additional data
- a "push" operation has the byte 'P', the data consists of the type to push (a byte consisting of one base flag from SGS_VT_*) and the binary data of the type
- a "call" operation has the byte 'C', the data consists of the number of arguments (4 bytes), function name length (1 byte) and the null-terminated function name itself (<length>+1 bytes)
Serialization
- "serialize" is called
- "sgs_Serialize" is called internally
- type of variable is determined and the data is written
- C functions cannot be serialized (obviously) and whenever encountered, will abort the action
- objects will have SERIALIZE operation called
- if operation is not defined, everything will stop
- if object is an array, all variables in it will be serialized using sgs_Serialize and sgs_SerializeObject will generate a call to 'array'
- if object is a 'dict' or a 'map', all keys and values in it will be serialized using sgs_Serialize and sgs_SerializeObject will generate a call to 'dict'
Deserialization
- "unserialize" is called
- the global environment could be changed
- "sgs_Unserialize" is called internally
- "push" and "call" operations are executed, thus regenerating the data
- "push" operation pushes a variable on the stack
- "call" operation calls the specified function
Possible gotchas
- unserialization is not by default safe in the sense that any function can be executed with a carefully crafted byte buffer; this can be prevented by specifying the second parameter to the "unserialize" function. the behavior can be reproduced with the C API but it will take a bit more effort or calling the "unserialize" function from it
- sgs_Serialize overrides the output function so any output done via "print" or "sgs_Write*" functions during serialization will corrupt the stream
- if environment overrides are used on deserialization, remember to add "array", "dict" and "map" to the list if you use them, they are not added automatically
- serialization will not preserve any variable reuse relationships so after deserialization the structure could use more memory than before; if more efficient behavior is desired, it is suggested to serialize an array of unique items and a structure of indices to those items
Secure sandbox environment
To ensure safety of the underlying environment, there are functions that need to be protected or disabled.
Critical (access to file system, possibility of taking control of the machine):
Information control (access to data about the system
Sandbox example
restrict = function( name )
{
println( "==\n= The use of '" $ name $ "' is restricted!\n==" );
};
closure = function( clbl, data )
{
return function() use( clbl, data )
{
args = va_get_args();
args.unshift( data );
sys_apply( clbl, this, args );
};
};
safe_include_lib = function( data, libname )
{
libname = tostring( libname );
if( ["string","math","re","fmt","os"].find( libname ) === null )
{
println( "info: cannot include files and system access libraries here" );
return;
}
data( libname );
if( libname == "os" )
{
unset( _G, "os_command" );
unset( _G, "os_getenv" );
unset( _G, "os_putenv" );
}
};
safe_include = function( libname )
{
return include_library( libname );
};
global include_library = closure( safe_include_lib, include_library );
global include = safe_include;
global include_shared = closure( restrict, "include_shared" );
global import_cfunc = closure( restrict, "import_cfunc" );
global include_file = closure( restrict, "include_file" );
global eval_file = closure( restrict, "eval_file" );
include "string", "math", "re", "fmt", "os";