SGScript documentation - v1.4.1 # SGScript - description [info] This is a programming language that is made to be fast, accessible and simple. ctrl.DReset(); foreach( at, item : speech ) { distfromlast = speech.size - at - 1; a = 0.9 * pow( 0.7, distfromlast ); ctrl.DCol( 0.9, a ); ctrl.DText( item.text, x + padding, y + padding + lineheight / 2, HALIGN_LEFT, VALIGN_CENTER ); y += lineheight; } 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. It adds dynamic typing and built-in serialization to C. Unlike Lua, it has C-like syntax and proper 0-based indexing and advanced object model, and much more versatile error handling. It has the consistency you'd want after working with PHP, and is considerably more lightweight. It untangles some of the mess JavaScript has introduced, and gives coroutines for a considerable boost in power of expression. And, unlike Python, SGScript won't care as much about formatting. You can find more about the differences at the "@"Why SGScript?"" page. The language supports: - `if/else`, `while`, `for`, `do/while`, `foreach` - 10 variable types: null, bool, int, real, string, function, C function, object, pointer, thread - Multi-level break/continue - Multiple return values - First-class functions and ability to attach variables to functions (creating closures) - Coroutines (with threading & sync primitives) The standard library includes: - array, dict, map - math, string, I/O, O/S and formatting functions - `eval`, file import, DLL import, coroutines - coroutines/threads, events, sync/race # >>> # Why SGScript? [info] == Native serialization [+] SGScript, Python [-] JavaScript, Lua, Squirrel Without any extra work, most of the data can be converted to a byte buffer so that it could be stored in a file or sent over a network and later converted back again. Languages that don't have it will require extra effort to get it and make sure it works with all kinds of custom objects. How much extra effort? Well, try googling for "lua serialize userdata". I didn't find a single way. SGScript - easy: @"https://github.com/snake5/sgscript/blob/6e9349a5a1ef5210ee440301b889f9afd78291be/ext/sgsxgmath.c#L248" == Reference counted memory management support [+] SGScript, Python, Squirrel [-] JavaScript, Lua This is a preferred method to garbage collection since it releases resources as soon as possible, avoiding random stalls throughout the game and thus providing a smooth gameplay experience. There are algorithms that reduce these stalls (incremental/generational garbage collection) but, given enough objects, they will be noticeable again. Source: @"http://sealedabstract.com/rants/why-mobile-web-apps-are-slow/" == Coroutines [+] SGScript, Lua, Squirrel, Python [-] JavaScript (only generators are supported) True cooperative multitasking allows the direction of timed events to be greatly simplified. SGScript goes one step further and also provides helper constructs (thread, subthread, sync, race) to make things as simple as possible for the user. == Custom native objects with complex links [+] SGScript, Python, JavaScript (partial support) [-] Lua, Squirrel These are objects that can be created in C/C++, with special interfaces that support operator overloading, serialization, debug printing, conversions, cloning, type name and iterator retrieval, index and property retrieval. If not used, this feature has no cost, however it helps greatly with defining fast and accessible interfaces by encapsulating native resource management and access. To see what SGScript objects are all about, check the previous GitHub link, there's quite a lot of them. == Native arrays [+] SGScript, Python, Squirrel, JavaScript (partial support) [-] Lua Native arrays (not to be confused with arrays that contain native data types, that is a subset of these) offer increased performance and memory-friendly storage over arrays made from hash tables. Array stores size as uint32, capacity as uint32 and values (16 bytes + extended data in SGScript) x size. A table would store all the same + keys (16 bytes + extended data) + hash array (size may differ but it's generally another array with size, capacity and a list of hash and index values). When arrays are considered, less (memory usage) is more (capacity). == Map support (all non-string/number keys) [+] SGScript, Python, JavaScript (requires the support of an extension) [-] Lua, Squirrel (some types are not supported in both) The ability to map any variable to any other variable provides extended metadata storage possibilities - it can be stored without modifying the original variable. m = map(); m[ sprite_obj ] = { high = 5 }; == Game math library [+] SGScript, Python, Lua, JavaScript [-] Squirrel A library with vector/matrix objects and functions for games. Not having to rewrite at least the bindings for it saves a lot of time. == Native debugging/profiling facilities [+] SGScript, Python, JavaScript (support differs between JS engines) [-] Lua, Squirrel Introspective debugging and time/memory usage profiling can help resolve various issues found. SGScript supports call stack time, instruction time and call stack memory usage profilers out-of-the-box. At any point, all data can be dumped via the built-in output facilities that can be rerouted to any file or parser. They are written in C to ensure a practically minimal performance impact while profiling. Significantly less than if the profiler was written in Lua, which is the main solution there. There's also access to some stats in SGScript so it is easy to see, for example, how many new allocations were done each frame. == Advanced native function argument parsing facilities. [+] SGScript, Python [-] Lua, Squirrel, JavaScript Every modern scripting engine should have a function that parses and validates function arguments according to a specification and puts the data in the specified locations. With bigger functions it saves you from writing a lot of boilerplate code. ==== SGScript: SGSFN( "fmt_string_parser" ); if( !sgs_LoadArgs( C, "?m|ii", &off, &bufsize ) ) // in case of type mismatch, emits a warning return 0; // ... and returns here to continue execution ==== Lua: (source: @"http://forums.tigsource.com/index.php?topic=36737.0") float x =luaL_checknumber(L,1); // in case of type mismatch, emits a fatal error, cannot continue script execution after this function call float y =luaL_checknumber(L,2); // same here const char* str=luaL_checkstring(L,3); // same here == Non-fatal error messaging facilities without exceptions [+] SGScript [-] Python, Lua, Squirrel, JavaScript This feature allows you to try and continue execution after a failed function call or intercept the error for debugging with the option of continuing later anyway. This is useful when code is published and there's a necessity to avoid going back to bug fixing immediately, before gathering more information about the state of the program. Why exceptions don't fit the criteria: they force the code to break out of the original execution path, thus severely reducing the usefulness of error suppression with logging. name = string_cut( other.name ); // warning: missing argument 2; after call, name = null // name gets printed somewhere as 'null' or is invisible due to some other function not accepting null for a string // everything else works == Built-in introspective pretty-printing (variable dumps) [+] SGScript, Python, JavaScript [-] Lua, Squirrel This is a very useful feature to have when you need to debug data (i.e. always). Simply passing a variable to some function (for example, printvar) prints some useful information about it - the type, contents, linked resources. == Warning suppression on missing property access [+] SGScript, Python (requires exception handling code) [-] Lua, Squirrel, JavaScript (no warnings about it at all) This feature allows to specify, per-read, whether the property is expected to be there or not. a = obj.prop; // expected, emits a warning if not found b = @obj.prop; // might not be there, no error This also works for many other actions, like function calls and assignments. == Custom native iterators [+] SGScript, Python [-] JavaScript, Lua, Squirrel An extension for custom native objects, it allows to create objects that can be foreach'ed through. foreach( entry : io_dir( "." ) ) println( entry ); // prints the contents of current directory == Dual access dictionaries [+] SGScript, Lua, JavaScript, Squirrel [-] Python The ability to access simple dictionaries just like any other object visually and syntactically reduces code complexity. a.b = x; // simple a["b"] = x; // not so simple == Explicit closures [+] SGScript [-] Lua, JavaScript, Squirrel, Python Explicit closures (specifying which local variables to pass over to the newly defined function) make it easier to read code using closures and prevents closure-related accidents, like having a variable changed unexpectedly. == Multi-index/property-set operation without temporary tables [+] SGScript [-] Lua, JavaScript, Squirrel, Python Simplifying code further without the introduction of sub-optimal memory access patterns. SGScript: obj.{ // object name written only once, accessed only once a = 1, // property write b = 2, // property write c = 3, // property write d = 4, // property write }; Lua, method 1: obj.a = 1 // property write obj.b = 2 // property write obj.c = 3 // property write obj.d = 4 // property write // object name written four times, accessed possibly four times (depending on compiler) Lua, method 2: for k, v in pairs({ a = 1, b = 2, c = 3, d = 4 }) do // create table, property write x4, function call, create closure obj[ k ] = v // object access x4, property write x4 end == C-like syntax [+] SGScript, JavaScript, Squirrel [-] Lua, Python With the overwhelming majority of code being written in C-like languages (@"http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"), having a compatible syntax helps when you need to copy code - there's simply less changes to perform. == Indices start at 0 [+] SGScript, JavaScript, Squirrel, Python [-] Lua Even though it is argued that 1-based indexing may help someone understand code better (which is actually hard to prove), I have a few arguments to make against it: - Array index is generally the distance (or as programmers would rather say, offset) from first element. 1 - 1 = 0. Not a distance from 0th element that doesn't even exist. Not the first element itself because elements have no keys in arrays. - Programming languages don't exist in a vacuum. Almost every other programming language treats indices as distances (offsets). Going against the grain makes it hard to interpret both languages at once for comparison or interface design. Whoever has to write that binding, has to keep in mind this difference for every array access made in the binding area. This is brain power not spent well. - Similarly to previous argument, this difference makes porting code from other languages harder. # Code samples - SGScript [info] === 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; } === Control flow 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 control flow 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 [info] === 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 ); # <<< # Language reference [info] # >>> # Variable types [info] SGScript has 10 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 - `ptr`: the pointer type - `thread`: the context/thread/coroutine type 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 - `event`: an object that allows to stop a thread # >>> # Conversion rules [info] ---------------------------------------------------------------------------------------------------------------------- ! 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) | - | | thread | true | cast | cast | sprintf thread(%p) | cast | ---------------------------------------------------------------------------------------------------------------------- - "-" 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 [info] Code can contain constants, identifiers, expressions and statements. Statements usually include expressions but expressions can also include statements, specifically - function expressions. # >>> # Constants [info] 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 [info] 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 | | _R | special identifier, read-only | global registry access | | _F | special identifier, read-only | current function retrieval | | _T | special identifier, read-only | current thread retrieval | | null | constant | constant | | true | constant | constant | | false | constant | constant | | var | restricted keyword | variable declaration | | global | restricted keyword | variable declaration | | class | special identifier | class declaration | | new | restricted keyword | class instantiation | | thread | restricted keyword | thread control | | subthread | restricted keyword | thread control | | sync | restricted keyword | thread control | | race | restricted keyword | thread control | | defer | restricted keyword | destruction statement helper | | 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 | | print | function command | "print" function | | println | function command | "println" function | | yield | function command | "yield" function | | include | function command | "include" function | ------------------------------------------------------------------------------------ # Expressions [info] 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, bitwise, logical, 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 | | bitwise AND |` A & B `| bitwise | no | 2 | | bitwise OR |` A | B `| bitwise | no | 2 | | bitwise XOR |` A ^ B `| bitwise | no | 2 | | left shift |` A << B `| bitwise | no | 2 | | right shift |` A >> B `| bitwise | no | 2 | | bitwise AND-assign |` A &= B `| bitwise | yes | 2 | | bitwise OR-assign |` A |= B `| bitwise | yes | 2 | | bitwise XOR-assign |` A ^= B `| bitwise | yes | 2 | | left shift-assign |` A <<= B `| bitwise | yes | 2 | | right shift-assign |` A >>= B `| bitwise | yes | 2 | | bitwise invert |` ~ A `| bitwise | no | 1 | | logical AND |` A && B `| logical | no | 2 | | logical OR |` A || B `| logical | no | 2 | | first-not-null |` A ?? B `| logical | no | 2 | | logical AND-assign |` A &&= B `| logical | yes | 2 | | logical OR-assign |` A ||= B `| logical | yes | 2 | | first-not-null-assign |` A ??= B `| logical | yes | 2 | | logical invert |` ! A `| logical | 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 | | map literal |` map{[A]=B} `| special | no | any | | assign |` A = B `| special | yes | 1 | | concatenate |` A $ B `| special | no | 2 | | concatenate-assign |` A $= B `| special | yes | 2 | | 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[]`| special | yes | any | | multi-property-assign |` A. `| 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 | | thread-call |` thread f() `| special | maybe | <=256 | | subthread-call |` subthread f()`| special | maybe | <=256 | | new-call |` new f() `| special | maybe | <=256 | ------------------------------------------------------------------------------ Some notes on the special cases: - [increment,decrement] pre-increment and pre-decrement operators return the modified value, post- operators - the original one - [logical] all logical operators except 'logical 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: = - 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 - [dict./map literal] 3 types of keys are supported: string, identifier (interpreted as string), variable ("[ ] = ") - [function] the full function definition expression syntax: `function ( ) [ use ( ) ]`, followed by either `{ ... }` or `= ... ;`. , and the 'use' block are all optional. - [multi-set] operator returns `A`, that is, the object itself - [thread] `thread`/`subthread` commands support all kinds of calls (`f()`, `o.f()`, `o!f()`) - [new] `new` supports only the basic calls (`f()`, `o.f()`), and `this` is not passed (as it would refer to the newly created instance) ==== 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. Object and its processing function can reside in different locations (like class instance / inherited class) and still be easily accessible. Properties: - uses the same symbol as logical inversion operator - usage: simplified & optimized calling of non-integrated compatible functions -- instead of `comp_func.call( object, arg1 )` (removed since 1.4) write `object!comp_func( arg1 )` -- instead of putting functions with data / class interfaces, requiring additional 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 [info] 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: `[, [, ...]] ;` - block statement: `{ [[, ...]] }` Examples: a = 5; a = 1, b = 2; === Control flow 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( ) [ else ]` - while: `while( ) ` - for: `for( ; ; ) ` - foreach: `foreach( [,][] : ) ` - do/while: `do while( )` - break: `break ;` - continue: `continue ;` - return: `return ;` - defer: `defer ` Examples: if( a ) { print( "a is true" ); } else print( "a is not true" ); while( b > 0 ) b--; `defer` is a special case since it moves the given statement to the end of the block (however that is reached). This can be useful for resource acquisitions: rsrc = acquire_resource(); defer release_resource( rsrc ); if( work_with( rsrc ) ) return; // release_resource is called here more_work_with( rsrc ); // .. and here === Declaration statements Statements that begin with "var", "global", "function" or "class" declare and set variables. Examples: var x = 5, y = 6, z; global World = null; function fn(){ INFO( "'fn' was called" ); } class C { var s = 1; function f(){ INFO( "'C.f' 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 [[, ...]];` - for each entry, a function call is generated - print: `print [[, ...]];` - one function call is generated for all items Examples: include "io", "string"; print "Count: ", count; # Built-in accessors [info] 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 | | apply | SGS/C function | property | function that allows to specify "this" & arg. array | | was_aborted| thread | property | returns if thread was aborted | | not_started| thread | property | returns if coroutine was not started yet | | running | thread | property | returns if thread is currently running | | can_resume | thread | property | returns if thread is not finished (can be resumed) | | end_on | thread | property | function that can specify an event to end the thread| | resume | thread | property | function that can resume the thread (see @co_resume)| | abort | thread | property | function that can abort the thread (see @abort) | -------------------------------------------------------------------------------------------------------- # Classes [info] == Basic class class SampleClass // create a class { // static member variable (can be read from both class definition and instance) global StaticVariable = 5; // the default construction function function __construct( x ) { // instance member variable (can be read only from class instance, not definition) this.c = x; } // static construction function function Create( x ) { return new SampleClass( x ); } function SampleMethod( a, b ) // "SampleClass.SampleMethod" 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 SampleFunction( a, b ) { return a + b; } } // instances of class inst1 = new SampleClass( 123 ); inst2 = SampleClass.Create( 456 ); // inspect instance 1, instance 2 and the underlying interface of instance 1 printvar( inst1, inst2, metaobj_get( inst1 ) ); == Inheritance // class A - base class class A { function func() { println( "base" ); } } // class B - inherits from A class B : A { function func() { this!A.func(); println( "override" ); } } instA = new A(); instB = new B(); instA.func(); // prints "base" instB.func(); // prints "base", then "override" Overloadable operators/interfaces (@Metamethods): - basic math: +, - (both unary and binary), *, /, % - comparison - conversions to `bool` and `string` - typeof string retrieval - cloning - function call # <<< # Numeric string parsing rules [info] ">>>" 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 [info] 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 [info] This part of the documentation describes the various types and definitions used in the C API. # >>> # Main types [info] Return types: - SGSRESULT [int]: output code (success = 0, failure: < 0 ) - SGSBOOL [int]: simplified output code (success = 1, failure = 0) - SGSONE [int]: always returns 1 - SGSZERO [int]: always returns 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 data types: - sgs_RegFuncConst [struct { const char*, sgs_CFunc }]: function registration unit - sgs_RegIntConst [struct { const char*, sgs_Int }]: integer registration unit - sgs_RegRealConst [struct { const char*, sgs_Real }]: real value registration unit - sgs_ScriptFSData [struct { void*, const char*, void*, size_t }]: virtual file system request data Interface function 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 - sgs_ScriptFSFunc [SGSRESULT ( void*, sgs_Context*, int, sgs_ScriptFSData* )]: virtual file system function # Error codes [info] 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_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 -- SGS_APIERR: API usage errors -- SGS_INTERR: internal errors -- any other integer may be defined and returned by other interfaces # Variable type codes [info] - SGS_VT_NULL: null - SGS_VT_BOOL: boolean - SGS_VT_INT: integer - SGS_VT_REAL: real value - SGS_VT_STRING: string - SGS_VT_FUNC: SGS function - SGS_VT_CFUNC: C function - SGS_VT_OBJECT: object - SGS_VT_PTR: pointer - SGS_VT_THREAD: thread/coroutine/context # <<< (Constants and types) # Concepts & systems [info] # >>> # Messaging system [info] 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 @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 [info] 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", @"sgs_GetIterator" ), advancing ( @"sgs_IterAdvance" ) and data retrieval ( @"sgs_IterPushData", @"sgs_IterGetData" ). 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, sgs_StackItem( C, -1 ) ); while( sgs_IterAdvance( C, sgs_StackItem( C, -1 ) ) > 0 ) { sgs_StackIdx ssz = sgs_StackSize( C ); sgs_IterPushData( C, sgs_StackItem( 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_GetIterator( C, iterable, &iterator ); while( sgs_IterAdvance( C, iterator ) > 0 ) { sgs_IterGetData( C, iterator, NULL, &value ); // .. use value .. sgs_Release( C, &value ); sgs_IterGetData( 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 [info] 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. # Metamethods [info] List of available metamethods: === __getindex - **When called**: on sub-index/property retrieval - **Arguments**: key - **Return value**: any - special value: @mm_getindex_router - routes __getindex to __get_*** === __setindex - **When called**: on setting sub-indices/properties - **Arguments**: key, value - **Return value**: none - special value: @mm_setindex_router - routes __setindex to __set_*** === __typeof - **When called**: on type string retrieval (@typeof / @sgs_TypeOf) - **Arguments**: none - **Return value**: type string === __clone - **When called**: on cloning operation (@clone / @sgs_Clone) - **Arguments**: none - **Return value**: the item to return as the cloned object === __tobool - **When called**: on bool value retrieval - **Arguments**: none - **Return value**: bool === __tostring - **When called**: on string value retrieval - **Arguments**: none - **Return value**: string === __negate - **When called**: on negation (`-obj`) - **Arguments**: none - **Return value**: the negated object === __add - **When called**: on addition (`var1 + var2`) when one of the variables has this interface defined - **Arguments**: operands A and B (types are not restricted) - **Return value**: the product of addition === __sub - **When called**: on subtraction (`var1 - var2`) when one of the variables has this interface defined - **Arguments**: operands A and B (types are not restricted) - **Return value**: the product of subtraction === __mul - **When called**: on multiplication (`var1 * var2`) when one of the variables has this interface defined - **Arguments**: operands A and B (types are not restricted) - **Return value**: the product of multiplication === __div - **When called**: on division (`var1 / var2`) when one of the variables has this interface defined - **Arguments**: operands A and B (types are not restricted) - **Return value**: the product of division === __mod - **When called**: on modulo (`var1 % var2`) when one of the variables has this interface defined - **Arguments**: operands A and B (types are not restricted) - **Return value**: the product of modulo === __compare - **When called**: on comparison (`var1 + var2`) when one of the variables has this interface defined - **Arguments**: operands A and B (types are not restricted) - **Return value**: the result of comparison (real value indicating < 0 if A 0 if A>B, = 0 if A=B) === __call - **When called**: on function call - **Arguments**: arguments from the original call - **Return value**: any # Closures [info] 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.. }` # <<< (Concepts & systems) # Functions [info] # >>> # Context management [info] - @sgs_CreateEngine - create scripting engine context - @sgs_CreateEngineExt - create scripting engine context and pass a custom memory function - @sgs_DestroyEngine - validate memory statistics and destroy engine context - @sgs_RootContext - find the root context - @sgs_ForkState - create a duplicate of the execution state - @sgs_ReleaseState - release an execution state - @sgs_PauseState - suspends the execution state - @sgs_ResumeStateRet - resumes the execution state, retrieves number of return values - @sgs_ResumeStateExp - resumes the execution state, returns the specified number of return values - @sgs_ResumeState - resumes the execution state without passing or receiving anything - @sgs_CreateSubthread - creates a thread (managed coroutine) with a starting function - @sgs_ProcessSubthreads - processes all subthread belonging to this state - @sgs_EventState - sets the event state - @sgs_EndOn - associates or detaches the event from thread end set - @sgs_DefaultMemFunc - example memory management callback - @sgs_Get(Err)OutputFunc - return the current output callback and its user data pointer - @sgs_Set(Err)OutputFunc - set the output callback and its user data pointer - @sgs_GetMsgFunc - return the current messaging callback and its user data pointer - @sgs_SetMsgFunc - set the messaging callback and its user data pointer - @sgs_GetScriptFSFunc - return the current virtual file system callback and its user data pointer - @sgs_SetScriptFSFunc - set the virtual file system callback and its user data pointer - @sgs_StdScriptFSFunc - default virtual file system function - @sgs_Cntl - set and/or retrieve various states in the system # Memory management [info] - @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) # Input / output [info] - @sgs_Get(Err)OutputFunc - return the current output callback and its user data pointer - @sgs_Set(Err)OutputFunc - set the output callback and its user data pointer - @sgs_(Err)Write - pass a character buffer to the output callback - @sgs_(Err)Writef - pass a formatted string to the output callback - @sgs_(Err)WriteStr - pass a null-terminated string to the output callback - @sgs_GetMsgFunc - return the current messaging callback and its user data pointer - @sgs_SetMsgFunc - set the messaging callback and its user data pointer - @sgs_Msg - invoke the messaging system - @sgs_WriteErrorInfo - write message info to output callback - @sgs_PushErrorInfo - push message info to stack - @sgs_HasFuncName - check if current C function has a name set - @sgs_FuncName - set current C function name - @SGSFN - set current C function name - @SGSBASEFN - set current C function name if it's not already set - @sgs_Errno - copy errno to internal errno if 2nd argument is false, otherwise clear it - @sgs_SetErrno - set the internal errno value - @sgs_GetLastErrno - return the currently set internal errno value - @sgs_StdOutputFunc - example output callback - @sgs_StdMsgFunc_NoAbort - example messaging callback that does not abort on errors - @sgs_StdMsgFunc - example messaging callback - @sgs_Cntl - set and/or retrieve various states in the system - @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) # Code handling [info] - @sgs_ExecBuffer - execute a character buffer - @sgs_EvalBuffer - execute a character buffer, keep returned variables on stack - @sgs_ExecString - execute a null-terminated string - @sgs_EvalString - execute a null-terminated string, keep returned variables on stack - @sgs_ExecFile - execute a file - @sgs_EvalFile - execute a file, keep returned variables on stack - @sgs_Include - include an item from the file system - @sgs_IncludeExt - include an item from the file system, optionally specifying a search path - @sgs_Compile - compile character buffer to bytecode buffer - @sgs_DumpCompiled - dump bytecode/constant info from a compiled bytecode buffer - @sgs_GetScriptFSFunc - return the current virtual file system callback and its user data pointer - @sgs_SetScriptFSFunc - set the virtual file system callback and its user data pointer - @sgs_StdScriptFSFunc - default virtual file system function # Introspection / debugging helpers [info] - @sgs_Stat - retrieve or dump various parts of VM state - @sgs_StackFrameInfo - retrieve preprocessed info from stack frame - @sgs_GetFramePtr - return a stack frame pointer - @sgs_DebugDumpVarExt - push a string containing variable data and return const char* to it - @sgs_DebugDumpVar - push a variable dump string and return const char* to it - @sgs_DebugPrintVar - push a string, converted from variable and return const char* to it - @sgs_CodeString - retrieve a name string for the specified constant - @sgs_WriteErrorInfo - write message info to output callback - @sgs_PushErrorInfo - push message info to stack # Execution control [info] - @sgs_XFCall - call variable as function - @sgs_XCall - call variable as function without `this` passed to it - @sgs_XThisCall - call variable as function function with `this` passed to it - @sgs_FCall - call variable as function - @sgs_Call - call variable as function without `this` passed to it - @sgs_ThisCall - call variable as function 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 # Binding helpers [info] - @sgs_LoadLib_Fmt - load the formatting library - @sgs_LoadLib_IO - load the input/output library - @sgs_LoadLib_Math - load the math library - @sgs_LoadLib_OS - load the operating system library - @sgs_LoadLib_RE - load the regular expression library - @sgs_LoadLib_String - load the string library - @sgs_RegFuncConsts - register a list of global C function constants - @sgs_RegIntConsts - register a list of global integer constants - @sgs_RegRealConsts - register a list of global real value constants - @sgs_StoreFuncConsts - store a list of C function constants in the specified variable - @sgs_StoreIntConsts - store a list of integer constants in the specified variable - @sgs_StoreRealConsts - store a list of real value constants in the specified variable # Object type storage [info] - @sgs_RegisterType - register an object interface pointer by name - @sgs_UnregisterType - unregister an object interface pointer by name - @sgs_FindType - find a registered object interface pointer by name - @sgs_IsType - check if variable on stack is of specified registered type - @sgs_IsTypeP - check if variable is of specified registered type - @sgs_PushInterface - push a cached/generated object - @sgs_InitInterface - initialize a variable to a cached/generated object # Variable initialization [info] - @sgs_MakeNull - initialize variable to a null variable - @sgs_MakeBool - initialize variable to a boolean variable - @sgs_MakeInt - initialize variable to an integer - @sgs_MakeReal - initialize variable to a real value - @sgs_MakeCFunc - initialize variable to C function - @sgs_MakePtr - initialize variable to a pointer variable - @sgs_InitStringBuf - initialize variable to a new char buffer - @sgs_InitString - initialize variable to a new string - @sgs_InitObjectPtr - initialize variable to an existing object and acquire it - @sgs_InitThreadPtr - initialize variable to a thread (context/coroutine) and acquire it - @sgs_CreateObject - initialize variable to a new object - @sgs_CreateObjectIPA - initialize variable to a new object with additional memory allocated in-place for the internal data pointer - @sgs_CreateArray - initialize variable to a new array, optionally using the specified number of pushed items on stack - @sgs_CreateDict - initialize variable to a new dict, optionally using the specified number of pushed items on stack - @sgs_CreateMap - initialize variable to a new map, optionally using the specified number of pushed items on stack - @sgs_CreateEvent - initialize variable to a new event - @sgs_CreatePooledEventBuf - initialize variable to a new or existing pooled event (by name in buffer) - @sgs_CreatePooledEvent - initialize variable to a new or existing pooled event (by C-string name) # Stack primary interface [info] - @sgs_PushNull - push a null variable - @sgs_PushNulls - push multiple null variables - @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_PushCFunc - push a C function - @sgs_PushPtr - push a pointer - @sgs_PushObjectPtr - push an object pointer - @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_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_SetDeltaSize - relative-resize the current stack frame - @sgs_AdjustStack - change stack size to from returned argument count to expected - @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_OptStackItem - return without acquisition the specified variable on stack without errors - @sgs_StackItem - return 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 - @sgs_StoreFuncConsts - store a list of C function constants in the specified variable - @sgs_StoreIntConsts - store a list of integer constants in the specified variable - @sgs_StoreRealConsts - store a list of real value constants in the specified variable # Sub-item usage [info] - @sgs_GetIndex - retrieve a sub-item - @sgs_SetIndex - set a sub-item - @sgs_PushIndex - retrieve and push a sub-item - @sgs_GetGlobal - retrieve a global variable - @sgs_SetGlobal - set a global variable - @sgs_PushGlobalByName - retrieve and push the global variable, specified by a string - @sgs_GetGlobalByName - retrieve the global variable, specified by a string - @sgs_SetGlobalByName - set a global variable, specified by a string - @sgs_PushProperty - retrieve and push the string property of a variable - @sgs_SetProperty - set a string property of a variable - @sgs_PushNumIndex - retrieve and push the integer index of a variable - @sgs_SetNumIndex - set an integer index of a variable - @sgs_Registry - retrieve a table from registry - @sgs_GetEnv - retrieve the global environment table - @sgs_SetEnv - set the variable as the global environment table, if possible - @sgs_PushEnv - push the global environment table - @sgs_PushPath - retrieve and push a variable from a path of sub-items - @sgs_StorePath - store and pop the topmost stack item into a path of sub-items # Argument handling [info] - @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 - @sgs_ArgCheck_Object - argument parsing function for parsing any objects - @sgs_ObjectArg - returns the additional integer argument for object interface function calls # Virtual machine operations [info] - @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_RegSymbol - register a persistent item (symbol) by the specified prefix/name - @sgs_GetSymbol - map name to a registered variable or variable to name using the symbol table - @sgs_Serialize(Ext) - serialize the given variable by converting it recursively to a byte stream - @sgs_Unserialize(Ext) - unserialize the given variable from a byte stream - @sgs_SerializeObject - specify the unserialization function and argument count to use for the object - @sgs_SerializeObjIndex - serialize an object's property/index - @sgs_SerializeSGSON - serialize the given variable into a text format - @sgs_UnserializeSGSON(Ext) - unserialize the given variable from a byte stream # String helpers [info] - @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 # Container helpers [info] - @sgs_IsArray - return if variable is of `array` type - @sgs_IsDict - return if variable is of `dict` type - @sgs_IsMap - return if variable is of `map` type - @sgs_ArraySize - return array size or -1 if variable is not an array - @sgs_ArrayPush - push the last `count` variables on stack to the end of the array `var`, then pop them from the stack - @sgs_ArrayPop - pop the last `count` variables off the end of the array `var`, optionally return them - @sgs_ArrayErase - remove the specified variable range [`at`,`at`+`count`) from array `var` - @sgs_ArrayFind - return the first position of item `what` in array `var` or -1 if item was not found - @sgs_ArrayRemove - remove first/all occurrence(s) of `what` in array `var` - @sgs_Unset - unset the specified index of the given `dict`/`map` variable, return if successful # Data retrieval & conversion [info] - @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_ArraySize - 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_IsArray - return if variable is of `array` type - @sgs_IsDict - return if variable is of `dict` type - @sgs_IsMap - return if variable is of `map` type - @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 - @sgs_ObjSetMetaObj - set meta-object of an object - @sgs_ObjGetMetaObj - retrieve meta-object of an object - @sgs_ObjSetMetaMethodEnable - enable or disable metamethod support for an object - @sgs_ObjGetMetaMethodEnable - check if metamethod support is enabled for an object # Iterators [info] - see @"Iterator system" for info on how these functions are to be used - @sgs_PushIterator - create and push iterator from variable - @sgs_GetIterator - create iterator from variable - @sgs_IterAdvance - advance iterator, specified by its variable - @sgs_IterPushData - extract and push data of current iteration of the iterator, specified by its variable - @sgs_IterGetData - extract data of current iteration of the iterator, specified by its variable # Variable ownership [info] - @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 - @sgs_ObjSetMetaObj - set meta-object of an object - @sgs_ObjGetMetaObj - retrieve meta-object of an object - @sgs_ObjSetMetaMethodEnable - enable or disable metamethod support for an object - @sgs_ObjGetMetaMethodEnable - check if metamethod support is enabled for an object # String generation helper interface [info] - @sgs_PushStringAlloc - push an uninitialized string buffer - @sgs_InitStringAlloc - set an uninitialized string buffer to a variable - @sgs_FinalizeStringAlloc(P) - finalize (prepare for usage) an uninitialized string buffer # Utility functions [info] - @sgs_CodeString - retrieve a name string for the specified constant - @sgs_IsNumericString - check if string is going to be parsed as a number by the internal parser # ALL functions (A-Z) [info] ~!~ render = list_pages_asc ~!~ filter_type = function,functions,function alias,function aliases # 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. - All execution state, object and any other engine-allocated pointers will be invalid after this call. # sgs_RootContext [function] == sgs_RootContext( sgsContext* C ) === Returns the root context of the engine. - Root context is the context that was returned from @sgs_CreateEngine / @sgs_CreateEngineExt. -- Root context is useful because it can only be destroyed last, so it's persistent. - If C = NULL, function returns NULL. # sgs_ForkState [function] == sgs_Context* sgs_ForkState( sgs_Context* C, int copystate ) === Creates a copy of the execution state. - If `copystate` is nonzero, all stacks (variable, closure, call) are copied as well, creating an exact duplicate. # sgs_ReleaseState [function] == sgs_ReleaseState( sgs_Context* C ) === Releases the execution state, possibly destroying the VM. - If the freed state is the last one that exists, function behaves exactly as @sgs_DestroyEngine. # sgs_PauseState [function] == SGSBOOL sgs_PauseState( sgs_Context* C ) === Suspends the execution state, prompting the VM to return control to caller. - A state cannot be suspended if call stack contains C functions or unusual constructs (at the moment some object interface calls may not work either). - This function can be used in a C function that was called from a SGS function. # sgs_ResumeState*** [functions] == SGSBOOL sgs_ResumeStateRet( sgs_Context* C, int args, int* outrvc ) === Resumes the execution state, passing arguments and retrieving the number of returned values. == SGSBOOL sgs_ResumeStateExp( sgs_Context* C, int args, int expect ) === Resumes the execution state, passing arguments and retrieving the specified number of returned values. - Returns true if state was suspended and thus subsequently resumed. - `args` must be bigger than or equal to the stack size. - `outrvc` can be NULL. # sgs_ResumeState [function alias] == SGSBOOL sgs_ResumeState( sgs_Context* C ) === Resumes the execution state. - Alias to `sgs_ResumeStateExp( C, 0, 0 )`. # sgs_CreateSubthread [function] == void sgs_CreateSubthread( sgs_Context* T, sgs_Context* C, sgs_Variable* out, sgs_StkIdx args, int gotthis ) === Creates a thread (managed coroutine) with a starting function. - `T` is the parent thread (use @sgs_RootContext for a global thread and same as `C` for a local thread). - `C` contains the function and arguments. - If `out` is `NULL`, new thread is pushed to `C`'s stack, otherwise it is assigned to that variable. - `args` and `gotthis` specify how to interpret the values pushed on stack (function expects `args + (gotthis?1:0) + 1` values). - Thread is started before returning from this function. # sgs_ProcessSubthreads [function] == int sgs_ProcessSubthreads( sgs_Context* C, sgs_Real dt ) === Advances all subthreads belonging to this state, using the given delta time. - Every subthread is resumed, waiting timers are advanced. # sgs_EventState [function] == SGSBOOL sgs_EventState( sgs_Context* C, sgs_Variable evt, int state ) === Sets the event state. - Function returns the previous state of the event. - `evt` must be the event object. - `state` can be one of these values: `SGS_TRUE`, `SGS_FALSE` or `SGS_QUERY`. -- `SGS_QUERY` doesn't modify the state, only returns it. # sgs_EndOn [function] == void sgs_EndOn( sgs_Context* C, sgs_Variable ev, int enable ) === Associates or detaches the event from thread end set. - @end_on is the SGScript version of this function. - `ev` can be any object, it should be an object with the "convert to bool" behavior implemented, such as the event object. -- The thread will interpret `true` as a request to stop. # 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_AdjustStack( C, 0, sgs_EvalBuffer( C, buf, sz ) )`. === 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 ) === Compiles and executes a string of text, leaving the return values on stack and returning their count. - To ignore return values, use @sgs_ExecString. - Alias to `sgs_EvalBuffer( C, str, SGS_STRINGLENGTHFUNC( str ) )`. === 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 ) === Compiles and executes a buffer of text or bytecode, leaving the return values on stack and returning their count. - To ignore return values, use @sgs_ExecBuffer. === 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_AdjustStack( C, 0, sgs_EvalFile( C, filename ) )`. === Error codes: - SGS_ECOMP: compiler error - SGS_EINVAL: passed data was not recognized - SGS_ENOTSUP: attempted to load a binary (no additional error is printed) # sgs_EvalFile [function] == SGSRESULT sgs_EvalFile( sgs_Context* C, const char* filename ) === Compiles and executes a file containing script text or bytecode, leaving the return values on stack and returning their count. - To ignore return values, use @sgs_ExecFile. === Error codes: - SGS_ECOMP: compiler error - SGS_EINVAL: passed data was not recognized - SGS_ENOTSUP: attempted to load a binary (no additional error is printed) # 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] == void sgs_LoadLib_Fmt( sgs_Context* C ) == void sgs_LoadLib_IO( sgs_Context* C ) == void sgs_LoadLib_Math( sgs_Context* C ) == void sgs_LoadLib_OS( sgs_Context* C ) == void sgs_LoadLib_RE( sgs_Context* C ) == void sgs_LoadLib_String( sgs_Context* C ) === Loads the library into the specified context - `Fmt`: string formatting library - `IO`: input/output library - `Math`: math library - `OS`: operating system info (date/time, environment, locale, terminal access) library - `RE`: regular expression library - `String`: string handling library # sgs_Reg***Consts [function] == void sgs_RegFuncConsts( sgs_Context* C, const sgs_RegFuncConst* list, int size ) == void sgs_RegIntConsts( sgs_Context* C, const sgs_RegIntConst* list, int size ) == void 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. # sgs_Make*** [functions] == sgs_Variable sgs_MakeNull() == sgs_Variable sgs_MakeBool( sgs_Bool value ) == sgs_Variable sgs_MakeInt( sgs_Int value ) == sgs_Variable sgs_MakeReal( sgs_Real value ) == sgs_Variable sgs_MakeCFunc( sgs_CFunc func ) == sgs_Variable sgs_MakePtr( void* ptr ) === Returns a variable instance of the specified type. - Since these are basic types, they don't need to be freed. - sgs_Bool is transformed to 0/1, everything else is unchanged. # sgs_Init*** [functions] == 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_InitObjectPtr( sgs_Variable* out, sgs_VarObj* obj ) == void sgs_InitThreadPtr( sgs_Variable* out, sgs_Context* T ) === Initialize a variable to the specified type. - Since these are reference-counted types, they need to be released manually. - To allocate an uninitialized string buffer, use @sgs_InitStringAlloc. # sgs_Create*** [functions] == SGSONE sgs_CreateObject( sgs_Context* C, sgs_Variable* out, void* data, sgs_ObjInterface* iface ) == void* sgs_CreateObjectIPA( sgs_Context* C, sgs_Variable* out, sgs_SizeVal added, sgs_ObjInterface* iface ) === Creates a new object. == SGSONE sgs_CreateArray( sgs_Context* C, sgs_Variable* out, sgs_SizeVal numitems ) === Creates an array from `numitems` last items on the stack, pops those items. == SGSONE sgs_CreateDict( sgs_Context* C, sgs_Variable* out, sgs_SizeVal numitems ) === Creates a dict from `numitems` last items on the stack, pops those items. == SGSONE sgs_CreateMap( sgs_Context* C, sgs_Variable* out, sgs_SizeVal numitems ) === Creates a map from `numitems` last items on the stack, pops those items. == SGSONE sgs_CreateEvent( sgs_Context* C, sgs_Variable* out ) === Initialize variable to a new event. == SGSONE sgs_CreatePooledEventBuf( sgs_Context* C, sgs_Variable* out, sgs_Variable dict, const char* str, sgs_SizeVal size ) === Initialize variable to a new or existing pooled event (by name in buffer). == SGSONE sgs_CreatePooledEvent( sgs_Context* C, sgs_Variable* out, sgs_Variable dict, const char* str ) === Initialize variable to a new or existing pooled event (by C-string name). - If `out` is unspecified, the new variable is pushed on the stack instead. - sgs_CreateObjectIPA 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_GetObjectData(P). # sgs_Push*** [functions] == SGSONE sgs_PushNull( sgs_Context* C ) == SGSONE sgs_PushNulls( sgs_Context* C, int count ) == SGSONE sgs_PushBool( sgs_Context* C, sgs_Bool value ) == SGSONE sgs_PushInt( sgs_Context* C, sgs_Int value ) == SGSONE sgs_PushReal( sgs_Context* C, sgs_Real value ) == SGSONE sgs_PushStringBuf( sgs_Context* C, const char* str, sgs_SizeVal size ) == SGSONE sgs_PushString( sgs_Context* C, const char* str ) == SGSONE sgs_PushCFunc( sgs_Context* C, sgs_CFunc func ) == SGSONE sgs_PushObject( sgs_Context* C, void* data, sgs_ObjInterface* iface ) == void* sgs_PushObjectIPA( sgs_Context* C, sgs_SizeVal added, sgs_ObjInterface* iface ) == SGSONE sgs_PushPtr( sgs_Context* C, void* ptr ) == SGSONE sgs_PushObjectPtr( sgs_Context* C, sgs_VarObj* obj ) == SGSONE sgs_PushVariable( sgs_Context* C, sgs_Variable* var ) === Pushes the data on the stack, as a new entry, appended to the end. ! To push objects, use @sgs_Create*** functions. ! To allocate an uninitialized string buffer, use @sgs_PushStringAlloc. - sgs_Bool is transformed to 0/1 before pushing, everything else is unchanged. - @sgs_PushVariable will increment the reference count of strings, SGS functions and objects. - Most functions here always return 1 (SGSONE), making them suitable for a "return sgs_Push***" construct. # sgs_StoreVariable [function] == void 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. # sgs_Pop [function] == void sgs_Pop( sgs_Context* C, int count ) === Pops `count` variables off the current frame of the stack. # sgs_PopSkip [function] == void sgs_PopSkip( sgs_Context* C, int count, int skip ) === Pops `count` variables off the current frame of the stack, skipping the last `skip` elements. # sgs_InsertVariable [function] == void 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. # sgs_PushItem [function alias] == void 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. - Alias of `sgs_PushVariable( C, sgs_StackItem( C, item ) )`. # sgs_GetIndex [function] == SGSBOOL sgs_GetIndex( sgs_Context* C, sgs_Variable obj, sgs_Variable idx, sgs_Variable* out, int isprop ) === Retrieve index/property `idx` from the specified variable `obj` to the position `out`, specifying retrieval type via `isprop`, return if successful. - On failure, out is set to a `null` variable. # sgs_SetIndex [function] == SGSBOOL sgs_SetIndex( sgs_Context* C, sgs_Variable obj, sgs_Variable idx, sgs_Variable val, int isprop ) === Set index/property `idx` in the specified variable `obj` to the value `val`, specifying type via `isprop`, return if successful. # sgs_PushIndex [function] == SGSBOOL sgs_PushIndex( sgs_Context* C, sgs_Variable obj, sgs_Variable idx, int isprop ) === Retrieve and push index/property `idx` from the specified variable `obj`, specifying retrieval type via `isprop`, return if successful. - On failure, `null` is pushed to stack. # sgs_PushProperty [functions] == SGSBOOL sgs_PushProperty( sgs_Context* C, sgs_Variable var, const char* name ) === Load and push the property of the variable `var` in the current stack frame, return if successful. - On failure, `null` is pushed to stack. # sgs_SetProperty [functions] == SGSBOOL sgs_SetProperty( sgs_Context* C, sgs_Variable var, const char* name, sgs_Variable val ) === Set the property `name` of variable `var` to `val`, return if successful. # sgs_PushNumIndex [function] == SGSBOOL sgs_PushNumIndex( sgs_Context* C, sgs_Variable var, sgs_Int idx ) === Load and push the integer index `idx` of the variable `obj`, return if successful. - On failure, `null` is pushed to stack. # sgs_SetNumIndex [function] == SGSBOOL sgs_SetNumIndex( sgs_Context* C, sgs_Variable var, sgs_Int idx, sgs_Variable val ) === Set the index `idx` of variable `var` to `val`, return if successful. # sgs_GetGlobal [function] == SGSBOOL sgs_GetGlobal( sgs_Context* C, sgs_Variable idx, sgs_Variable* out ) === Retrieve a global variable by index `idx` to position `out`. - On failure, out is set to a `null` variable. # sgs_SetGlobal [function] == SGSBOOL sgs_SetGlobal( sgs_Context* C, sgs_Variable idx, sgs_Variable val ) === Set global variable `idx` to `val`. - When setting `_G` (environment superglobal), `val` must be of `dict`/`map` type or the function will fail. # sgs_PushGlobalByName [function] == SGSBOOL sgs_PushGlobalByName( sgs_Context* C, const char* name ) === Push the global variable `name` on the stack, return if successful. - On failure, `null` is pushed to stack. # sgs_GetGlobalByName [function] == SGSBOOL sgs_GetGlobalByName( sgs_Context* C, const char* name, sgs_Variable* out ) === Retrieve the global variable `name`, return if successful. - On failure, out is set to a `null` variable. # sgs_SetGlobalByName [function] == SGSBOOL sgs_SetGlobalByName( sgs_Context* C, const char* name, sgs_Variable val ) === Set global variable `name` to `val`. - When setting `_G` (environment superglobal), `val` must be of `dict`/`map` type or the function will fail. # sgs_Registry [function] == sgs_Variable sgs_Registry( sgs_Context* C, int subtype ) === Retrieve a table from registry. - `subtype` can be one of: -- SGS_REG_ROOT: registry root (`_R`); -- SGS_REG_SYM: symbol table (`_R["$sym"]`); -- SGS_REG_INC: included file table (`_R["$inc"]`). # sgs_GetEnv [function] == void sgs_GetEnv( sgs_Context* C, sgs_Variable* out ) === Retrieve the global environment variable (_G). # sgs_SetEnv [function] == void sgs_SetEnv( sgs_Context* C, sgs_Variable* var ) === Set a global environment variable from the variable `var`. - Only `dict`/`map` types are accepted. # sgs_PushEnv [function] == void sgs_PushEnv( sgs_Context* C ) === Retrieve and push the global environment variable (_G). # sgs_PushPath [function] == SGSBOOL sgs_PushPath( sgs_Context* C, sgs_Variable var, const char* path, ... ) === Push the variable specified by starting point `var` and traversal path `path`, return if successful. ! 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]) # sgs_StorePath [function] == SGSBOOL sgs_StorePath( sgs_Context* C, sgs_Variable var, sgs_Variable val, const char* path, ... ) === Set value `val` to variable specified by starting point `var` 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. # sgs_Store***Consts [functions] == void sgs_StoreFuncConsts( sgs_Context* C, sgs_Variable var, const sgs_RegFuncConst* list, int size ) == void sgs_StoreIntConsts( sgs_Context* C, sgs_Variable var, const sgs_RegIntConst* list, int size ) == void sgs_StoreRealConsts( sgs_Context* C, sgs_Variable var, const sgs_RegRealConst* list, int size ) === Loads the specified list of constants in the specified variable. - 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. # 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] == SGSBOOL sgs_LoadArgsExt( sgs_Context* C, int from, const char* cmd, ... ) == SGSBOOL 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). ==== 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) - `I` -- check for `int` (returns int or unsigned int, depending on sign settings, 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) - `y` -- check for `thread` (returns sgs_Context*) - `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 specific `object` (requires sgs_ObjInterface* interface, returns * data - the data pointer) - `*` -- check for any `object` (returns sgs_ObjInterface* interface) - `&` -- 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) # 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. - For more info on syntax and usage, refer to @sgs_LoadArgsExt(VA). - Alias to `sgs_LoadArgsExt( C, 0, cmd, ... )`. # sgs_ParseMethod [function] == SGSBOOL sgs_ParseMethod( sgs_Context* C, sgs_ObjInterface* iface, void** ptrout, const char* name ); === Implements method parsing. - If object of the right type is first in the stack, its data pointer is received. - Function also registers its name to `name`. # SGS_PARSE_METHOD [function alias] == SGSBOOL SGS_PARSE_METHOD( sgs_Context* C, sgs_ObjInterface* iface, T*& ptrout, ident objname, ident methodname ) === Method parsing macro. - If object of the right type is first in the stack, its data pointer is received. - Function also registers its name to "objname.methodname". # 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_ArgCheck_Object [function] == int sgs_ArgCheck_Object( sgs_Context* C, int argid, va_list* args, int flags ) === Argument parsing function for parsing any objects. - To be used with @sgs_LoadArgs and related functions. - Strictness controls whether `null` is accepted. - Returned value: sgs_VarObj* (expects sgs_VarObj** argument for it). # sgs_ObjectArg [function] == int sgs_ObjectArg( sgs_Context* C ) === Returns the additional integer argument to an object interface function call. - For `getindex` and `setindex`: if argument is nonzero, property is requested, zero - index. # sgs_XFCall [functions] == int sgs_XFCall( sgs_Context* C, int args, int gotthis ) === Call the function with the arguments on stack, returning variables on stack and their count. - Refer to @sgs_FCall for additional documentation. # sgs_X(This)Call [function aliases] == int sgs_XCall( sgs_Context* C, int args ) == int sgs_XThisCall( sgs_Context* C, int args ) === Call the function with the arguments on stack, returning variables on stack and their count. - Aliases to @sgs_XFCall, for the first function `gotthis = 0`, for the second `gotthis = 1`. # sgs_FCall [functions] == int sgs_FCall( sgs_Context* C, int args, int expect, int gotthis ) === Call the function with the arguments on stack, returning the expected number of variables on stack. - `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. - Return value of function is the original number of returned values on stack from this call. After a successful call, all arguments 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 values, '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: -- [function] -- (if gotthis != 0) [this] -- [argument] x `args` - A callable is one of the following: -- SGS function -- C function -- object with CALL interface function defined ! To check if function call was aborted, see @sgs_Cntl / SGS_CNTL_GET_ABORT. ! To find out if execution state was suspended in this call, see @sgs_Cntl / SGS_CNTL_GET_PAUSED. # sgs_(This)Call [function aliases] == void sgs_Call( sgs_Context* C, int args, int expect ) == void sgs_ThisCall( sgs_Context* C, int args, int expect ) === Call the function with the arguments on stack, returning the expected number of variables on stack. - Aliases to @sgs_FCall, for the first function `gotthis = 0`, for the second `gotthis = 1`. # sgs_GlobalCall [function] == SGSBOOL sgs_GlobalCall( sgs_Context* C, const char* name, int args, int expect ) === Call the global variable `name` as a function. - Combination of global function retrieval and function call; see @sgs_PushGlobalByName and @sgs_FCall for more info on behavior. # sgs_TypeOf [function] == void sgs_TypeOf( sgs_Context* C, sgs_Variable var ) === Return the type name string of the specified variable. - Object type sources are processed in the following order: -- Metamethod `__typeof`; -- `sgs_ObjInterface::name`; -- If both methods failed, just return 'object'. # sgs_DumpVar [function] == void sgs_DumpVar( sgs_Context* C, sgs_Variable var, int maxdepth ) === Convert the variable to a highly informative string that should display its contents, up to `maxdepth` depth. - If object does not have the DUMP interface function implemented, only its pointer in memory and reference count are displayed. # sgs_GCExecute [function] == void 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 tables). # sgs_DebugDumpVarExt [functions] == const char* sgs_DebugDumpVarExt( sgs_Context* C, sgs_Variable var, int maxdepth ) === Push a string containing variable data and return const char* to it. - If `maxdepth` is negative, variable is converted to a normal string (sgs_ToString) instead of dump string (sgs_DumpVar). # sgs_DebugDumpVar [function alias] == const char* sgs_DebugDumpVar( sgs_Context* C, sgs_Variable* var ) === Push a variable dump string and return const char* to it. - Alias to `sgs_DebugDumpVarExt( C, var, 5 )`. - For more info, see @sgs_DebugDumpVarExt. # sgs_DebugPrintVar [function alias] == const char* sgs_DebugPrintVar( sgs_Context* C, sgs_Variable var ) === Push a string, converted from variable and return const char* to it. - Alias to `sgs_DebugDumpVarExt( C, var, -1 )`. - For more info, see @sgs_DebugDumpVarExt. # sgs_PadString [function] == void 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. # sgs_ToPrintSafeString [function] == void 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. # sgs_StringConcat [function] == void sgs_StringConcat( sgs_Context* C, int args ) === Concatenate the `args` number of topmost string variables in the current stack frame. - If `args` = 0, empty string is pushed. # sgs_CloneItem [function] == void sgs_CloneItem( sgs_Context* C, sgs_Variable var ) === 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. - Function will fail if any object attempted to be cloned does not support cloning. # sgs_RegSymbol [function] == void sgs_RegSymbol( sgs_Context* C, const char* prefix, const char* name, sgs_Variable var ) === Register a persistent item (symbol) by the specified prefix/name. - Symbols are used for serialization to map unserializable and persistent items in both ways, to preserve their linkage in the serialized data. - At least one of (`prefix`, `name`) must be set to a non-empty string. If both are set, they are concatenated in the given order. - This function is equivalent to @sym_register in the SGScript API. # sgs_GetSymbol [function] == SGSBOOL sgs_GetSymbol( sgs_Context* C, sgs_Variable var, sgs_Variable* out ) === Map name to a registered variable or variable to name using the symbol table. - This function is equivalent to @sym_get in the SGScript API. # sgs_Serialize(Ext) [functions] == void sgs_Serialize( sgs_Context* C, sgs_Variable var ) === Serialize the given variable (convert to a byte stream). == void sgs_SerializeExt( sgs_Context* C, sgs_Variable var, int mode ) === Same as above, also allows to specify serialization mode. - `sgs_Serialize` is alias of `sgs_SerializeExt( C, var, SGS_SERIALIZE_DEFAULT )` - Function pushes a string variable on stack if serialization was at least minimally successful, otherwise `null` is pushed. - Default serialization mode is 2 or the current mode inside object serialization callback. - The following variable types can be serialized: -- symbols (variables that can be found in the symbol table); -- null, bool, int, real, string, func (SGS function); -- objects with the SERIALIZE interface function defined. # sgs_Unserialize(Ext) [functions] == SGSBOOL sgs_Unserialize( sgs_Context* C, sgs_Variable var ) === Unserialize the given variable (decode the byte stream). == SGSBOOL sgs_UnserializeExt( sgs_Context* C, sgs_Variable var, int mode ) === Same as above, also allows to specify serialization mode. ! Be mindful of the data sources you use - calls to any global function can be placed in the byte stream. - `sgs_Unserialize` is alias of `sgs_UnserializeExt( C, var, SGS_SERIALIZE_DEFAULT )` - To make sure only the right functions can be called, the global environment can be replaced with @sgs_SetEnv. # sgs_SerializeObject [function] == void sgs_SerializeObject( sgs_Context* C, sgs_StkIdx args, const char* func ) === Specify the unserialization function and argument count to use for the object. # sgs_SerializeObjIndex [function] == void sgs_SerializeObjIndex( sgs_Context* C, sgs_Variable key, sgs_Variable val, int isprop ) === Serialize an object's property/index. - This function is used to serialize structures that may contain references to other variables... -- ...which leave them open to producing a self-referential construct that normal tree serialization cannot handle. - Only supported by serialization modes 1 and 2 (binary). -- Mode 1 support does not actually allow serializing self-referential structures. - For usage examples, see source code in `sgs_std.c`. # sgs_SerializeSGSON [function] == void sgs_SerializeSGSON( sgs_Context* C, sgs_Variable var, const char* tab ) === Serialize the given variable into a text format. - This is similar to `sgs_SerializeExt` with mode = 3, only difference being the `tab` argument. - `tab` allows to specify the string used for tabs -- if `tab` is `NULL`, the text output is tightly packed, without any extra spaces # sgs_UnserializeSGSON(Ext) [functions] == void sgs_UnserializeSGSON( sgs_Context* C, const char* str ) === Unserialize the given variable from a byte stream. == void sgs_UnserializeSGSONExt( sgs_Context* C, const char* str, size_t size ) === Allows to pass a string buffer to the parsing function. - `sgs_UnserializeSGSON` is alias to `sgs_UnserializeSGSONExt( C, str, SGS_STRINGLENGTHFUNC( str ) )` - This is the same as creating a string variable and calling `sgs_UnserializeExt( C, , 3 )` # sgs_Assign [function] == void sgs_Assign( sgs_Context* C, sgs_Variable* var_to, sgs_Variable* var_from ) === Acquire `var_from`, release `var_to`, copy `var_from` to `var_to`. # sgs_ArithOp [function] == void 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 6 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`) # sgs_IncDec [function] == void sgs_IncDec( sgs_Context* C, 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. # 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] == SGSBOOL sgs_RegisterType( sgs_Context* C, const char* name, sgs_ObjInterface* iface ) === Register a type interface by mapping it to a name. # sgs_UnregisterType [function] == SGSBOOL sgs_UnregisterType( sgs_Context* C, const char* name ) === Unregister a type interface by its name. # 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_PushInterface [function] == SGSONE sgs_PushInterface( sgs_Context* C, sgs_CFunc igfn ) === Push a cached/generated object. - If object is not in cache, it is generated from the specified function. # sgs_InitInterface [function] == void sgs_InitInterface( sgs_Context* C, sgs_Variable* var, sgs_CFunc igfn ) === Initialize a variable to a cached/generated object. - If object is not in cache, it is generated from the specified function. # 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_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 @. # 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_ParseStringP( sgs_Context* C, sgs_Variable* var, char** out, sgs_SizeVal* size ) === Attempts to parse the specified variable, returning whether parsing was successful. - The parsing rules: -- for `sgs_ParsePtr`, unlike every other parsing function, only null/ptr types are considered valid; -- for `sgs_ParseObjectPtr`, 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_Context* C, const char* name ) == sgs_Int sgs_GlobalInt( sgs_Context* C, const char* name ) == sgs_Real sgs_GlobalReal( sgs_Context* C, const char* name ) == char* sgs_GlobalStringBuf( sgs_Context* C, const char* name, sgs_SizeVal* outsize ) == char* sgs_GlobalString( sgs_Context* C, 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 [functions] == SGSBOOL sgs_PushIterator( sgs_Context* C, sgs_Variable var ) === Create and push an iterator from the specified variable, return if successful. - On failure, null is pushed. - See @"Iterator system" for more info about iterators. # sgs_GetIterator [functions] == SGSBOOL sgs_GetIterator( sgs_Context* C, sgs_Variable var, sgs_Variable* out ) === Create an iterator from the specified variable, return if successful. - On failure, out receives a null variable. - See @"Iterator system" for more info about iterators. # sgs_IterAdvance [functions] == SGSBOOL sgs_IterAdvance( sgs_Context* C, sgs_Variable var ) === Advance the iterator to the next position, returning if the current position is still in range. - This is the way it's expected to be usually called: `while( sgs_IterAdvance( C, var ) ){ ... sgs_IterPushData ... }`. - See @"Iterator system" for more info about iterators. # sgs_IterPushData [functions] == void sgs_IterPushData( 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. # sgs_IterGetData [functions] == void sgs_IterGetData( 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. # sgs_IsArray [function] == SGSBOOL sgs_IsArray( sgs_Variable var ) === Return if variable is of `array` type. # sgs_IsDict [function] == SGSBOOL sgs_IsDict( sgs_Variable var ) === Return if variable is of `dict` type. # sgs_IsMap [function] == SGSBOOL sgs_IsMap( sgs_Variable var ) === Return if variable is of `map` type. # sgs_ArraySize [functions] == sgs_SizeVal sgs_ArraySize( sgs_Variable var ) === Check if the specified stack item or variable is an array and return its size or -1 if variable is not an array. # sgs_ArrayPush [function] == void sgs_ArrayPush( sgs_Context* C, sgs_Variable var, sgs_StkIdx count ) === Push the last `count` variables on stack to the end of the array `var`, then pop them from the stack. # sgs_ArrayPop [function] == void sgs_ArrayPop( sgs_Context* C, sgs_Variable var, sgs_StkIdx count, SGSBOOL ret ) === Pop the last `count` variables off the end of the array `var`, optionally return them. - If `ret` != 0, variables are pushed on the stack before removal. # sgs_ArrayErase [function] == void sgs_ArrayErase( sgs_Context* C, sgs_Variable var, sgs_StkIdx at, sgs_StkIdx count ) === Remove the specified variable range [`at`,`at`+`count`) from array `var`. # sgs_ArrayFind [function] == sgs_SizeVal sgs_ArrayFind( sgs_Context* C, sgs_Variable var, sgs_Variable what ) === Return the first position of item `what` in array `var` or -1 if item was not found. # sgs_ArrayRemove [function] == sgs_SizeVal sgs_ArrayRemove( sgs_Context* C, sgs_Variable var, sgs_Variable what, SGSBOOL all ) === Remove first/all occurrence(s) of `what` in array `var`. # sgs_Unset [function] == SGSBOOL sgs_Unset( sgs_Context* C, sgs_Variable var, sgs_Variable key ) === Unset the specified index of the given `dict`/`map` variable, return if successful. # sgs_StackSize [function] == sgs_StkIdx sgs_StackSize( sgs_Context* C ) === Return the size of the current stack frame. # sgs_SetStackSize [function] == void 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_SetDeltaSize [function] == void sgs_SetDeltaSize( sgs_Context* C, sgs_StkIdx diff ) === Resizes the current stack frame to the [size+diff] size. - If diff is positive, stack is null-variable-padded at the end. - If diff is negative, the specified number of items are popped. - If amount of items to be popped is bigger than size, function fails. # sgs_AdjustStack [function] == SGSRESULT sgs_AdjustStack( sgs_Context* C, int expected, int ret ) === Resizes the current stack frame by `expected` - `ret`, returns `ret` Used with sgs_Eval** functions to create their sgs_Exec** counterparts. # 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_OptStackItem [function] == sgs_Variable sgs_OptStackItem( sgs_Context* C, sgs_StkIdx item ) === Returns a non-owned copy of a variable on stack or null if the index is invalid. - See @sgs_StackItem for details on behavior, only difference is that `null` is returned when an invalid stack index is passed. - This function is useful for the implementation of "Parse"/"ArgCheck" functions which are required never to throw errors by convention. # sgs_StackItem [function] == sgs_Variable sgs_StackItem( sgs_Context* C, sgs_StkIdx item ) === Returns a non-owned copy of a variable on stack. ! Avoid using this function with functions that can alter the stack and remove the source item. ! This function does not acquire the variable and thus can't be used in functions that modify it without previously taking ownership of it, such as @sgs_Assign or @sgs_To***; to acquire variable on retrieval, see @sgs_GetStackItem or @sgs_Acquire. - This function can be used to pass arguments from stack in most simple operations. # 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] == void sgs_SetStackItem( sgs_Context* C, sgs_StkIdx item, sgs_Variable val ) === Copy the specified variable to the specified position in stack. # 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] == void sgs_GCMark( sgs_Context* C, sgs_Variable* var ) == void 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] == void 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_ObjSetMetaObj [function] == void sgs_ObjSetMetaObj( sgs_Context* C, sgs_VarObj* obj, sgs_VarObj* metaobj ) === Set `metaobj` as the meta-object of object `obj`. - `obj` must always point to an object, `metaobj` can be NULL. # sgs_ObjGetMetaObj [function] == sgs_VarObj* sgs_ObjGetMetaObj( sgs_VarObj* obj ) === Retrieve meta-object of an object. - To retrieve an object from variable, use @sgs_GetObjectStruct(P). - `obj` must always point to an object. # sgs_ObjSetMetaMethodEnable [function] == void sgs_ObjSetMetaMethodEnable( sgs_VarObj* obj, SGSBOOL enable ) === Enable or disable metamethod support for an object. - To retrieve an object from variable, use @sgs_GetObjectStruct(P). - `obj` must always point to an object. # sgs_ObjGetMetaMethodEnable [function] == SGSBOOL sgs_ObjGetMetaMethodEnable( sgs_VarObj* obj ) === Check if metamethod support is enabled for an object. - To retrieve an object from variable, use @sgs_GetObjectStruct(P). - `obj` must always point to an object. # 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] == void sgs_SetObjectData( sgs_Context* C, sgs_StkIdx item, void* data ) === Set the object data pointer of the specified stack item. == void 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, and ... -- in a debug build, one of the BreakIf macros will go off and stop the action. # sgs_SetObjectIface(P) [functions] == void sgs_SetObjectIface( sgs_Context* C, sgs_StkIdx item, sgs_ObjInterface* iface ) === Set the object interface pointer of the specified stack item. == void 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, 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, ... ) == void sgs_ErrWritef( 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. - `printf` rules apply here. # 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 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( C ) ) sgs_FuncName( 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] == SGSBOOL sgs_Abort( sgs_Context* C ) === Stops execution of current SGS functions up to the last C function in the stack, excluding the current. - Function fails if there was nothing to abort - 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_STATECOUNT: returns the number of execution states created in 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_DUMP_SYMBOLS: dump the list of registered symbols; -- 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 using multiple versions should be supported / prevented. # 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; -- SGS_CNTL_NUMRETVALS: returns the real number of returned values from last function call; -- SGS_CNTL_GET_PAUSED: returns whether the execution state is suspended; -- SGS_CNTL_GET_ABORT: returns whether last function call was aborted; - 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 - ""). # sgs_GetFramePtr [function] == sgs_StackFrame* sgs_GetFramePtr( sgs_Context* C, sgs_StackFrame* from, int bwd ) === Returns a call stack frame pointer. - If `bwd` is 0, request a pointer for forward iteration: -- if `from` is NULL, return pointer to first frame, otherwise return the frame after `from` (or NULL if it doesn't exist). - If `bwd` is not 0, request a pointer for reverse iteration: -- if `from` is NULL, return pointer to last frame, otherwise return the frame before `from` (or NULL if it doesn't exist). # 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_PushStringAlloc [function] == char* sgs_PushStringAlloc( sgs_Context* C, sgs_SizeVal size ) === Push an uninitialized string buffer, returns pointer to buffer. Created string is a valid resource in terms of acquisition/release but not hashed and internalized yet, thus it cannot be used in indexing/comparison functions until it's finalized, see @sgs_FinalizeStringAlloc(P). - It is safe to write string data (to pointer retrieved from @sgs_GetStringPtr(P) function) up until finalization. # sgs_InitStringAlloc [function] == char* sgs_InitStringAlloc( sgs_Context* C, sgs_Variable* var, sgs_SizeVal size ) === Set an uninitialized string buffer to a variable, returns pointer to buffer. Created string is a valid resource in terms of acquisition/release but not hashed and internalized yet, thus it cannot be used in indexing/comparison functions until it's finalized, see @sgs_FinalizeStringAlloc(P). - It is safe to write string data (to pointer retrieved from @sgs_GetStringPtr(P) function) up until finalization. # sgs_FinalizeStringAlloc(P) [functions] == void sgs_FinalizeStringAlloc( sgs_Context* C, sgs_StkIdx item ) == void sgs_FinalizeStringAllocP( sgs_Context* C, sgs_Variable* var ) === Finalize (prepare for usage) an uninitialized string buffer. - Preparations include string hashing and internalization (release of owned copy in favor of exact same string in string table). - After using these functions, string data cannot be modified. # <<< (Functions) # Interface implementation [info] # >>> # C Functions [info] 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 [info] 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: - Before the object is about to be destroyed. - On @sgs_ObjCallDtor ==== 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: - object argument (see @sgs_ObjectArg) -- (0/1) whether this is a property read (1) or index read (0) ==== Stack frame: - Item 0 - key variable to be used to find a sub-item. - 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 - object argument (see @sgs_ObjectArg) -- (0/1) whether this is a property read (1) or index read (0) ==== Stack frame: - Item 0 - key variable to be used to find a sub-item. - Item 1 - value variable to be used in setting the value of the sub-item. ==== 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: - type conversion: to*** function families and other conversion triggers (like operators) in SGScript and the Get/To/Parse function families in the C API. - SGS_CONVOP_CLONE: called on @clone / @sgs_Clone - SGS_CONVOP_TOITER: called on foreach / @sgs_PushIterator / @sgs_GetIterator ==== Additional arguments: - int type -- one of SGS_VT_[BOOL|STRING] or SGS_CONVOP_CLONE / 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_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: - @serialize in SGScript. - @sgs_Serialize(Ext) in the C API. ==== 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: - @printvar, @dumpvar, @printvar_ext, @dumpvar_ext in SGScript. - @sgs_DumpVar in the C API. ==== 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: - @gc_collect in SGScript. - @sgs_GCMark / @sgs_GCExecute in the C API. ==== 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: - foreach in SGScript. - @sgs_IterAdvance / @sgs_IterPushData / @sgs_IterGetData ==== 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 [info] 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 --- SGS_HOOK_PAUSE - context was paused --- SGS_HOOK_CONT - context was resumed --- SGS_HOOK_CREAT - context was created (empty, no state copy) --- SGS_HOOK_CFORK - context was forked (full state copy) --- SGS_HOOK_CFREE - context was freed # <<< # Commonly required advanced tasks [info] === 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; - The OLD way, version 1: sgs_FuncName( C, "." ); if( !sgs_Method( C ) || !sgs_IsObject( C, 0, Object_interface_pointer ) ) return sgs_ArgErrorExt( C, 0, 1, "", "" ); 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 ? "." : "" ); if( !sgs_IsObject( C, 0, Object_interface_pointer ) ) return sgs_ArgErrorExt( C, 0, method_call, "", "" ); 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 [info] # >>> # Core library [info] 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 -- @map_filter - returns a map object that is filtered with a truth test or the specified function -- @map_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 - input/output -- @"print, println, printlns, errprint, errprintln, errprintlns" - write variables to output callback/stream -- @printvar - write variable dumps to output callback/stream -- @printvar_ext - write variable dump to output callback/stream, optionally specifying max. recursion depth -- @read_stdin - attempt to read from standard input file (stdin) - 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 -- @metaobj_set - sets the meta-object of an object -- @metaobj_get - retrieves the meta-object of an object -- @metamethods_enable - enables or disables metamethod support for an object -- @metamethods_test - retrieves metamethod support state -- @mm_getindex_router - routes __getindex to __get_*** -- @mm_setindex_router - routes __setindex to __set_*** -- @event - create an event -- @pooled_event - create a pooled event (named event, in table) -- @end_on - set or unset an event that can stop a thread -- @co_create - create a coroutine -- @co_resume - start/resume a coroutine -- @thread_create - create a managed topmost coroutine (thread) -- @subthread_create - create a managed sub-coroutine (subthread) -- @yield - suspend current state, return to caller -- @abort - stop the execution of the calling SGS function -- @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` -- @sym_register - register persistent object by name (for serialization) -- @sym_get - map name to a registered variable or variable to name using the symbol table -- @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 -- @find_include_file - find the include file according to SGS_PATH -- @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_curprocfile - returns the path to current process file -- @sys_curprocdir - returns the path to the directory of current process file -- @multiply_path_ext_lists - combine prefix/suffix path lists -- @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 -- @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 built-in methods: - @array -- @push -- @pop -- @shift -- @unshift -- @insert -- @erase -- @part -- @clear -- @reverse -- @resize -- @reserve -- @sort -- @sort_custom -- @sort_mapped -- @find -- @remove -- @unique -- @random -- @shuffle - @dict - @map === Constants: - @SGS_*** - error levels - @VT_*** - variable type IDs - @RAND_MAX - maximum value that can be returned by @rand === Other: - @_G<_G [superglobal]> - 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 (number of arguments is limited to 255 in the language, but not the API/serialization system) array( "5", 6, 7.0 ) // same as ["5",6,7.0] - the implementation of `array` is an object with __call metamethod. New methods can be added to `array`: function array.join( separator ) { return string_implode( this, separator ); } # array_sized [function] == array_sized( size ) === returns an @array, containing `size` null values # 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( object obj, object metaobj ) === sets `metaobj` as meta-object for `obj` and enables @metamethods for `obj`, returns `obj` - 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} # map_filter [function] == map_filter( map[, callable] ) === return a map with the items that convert to boolean 'true', optionally preprocessed by a callable - two arguments are passed to the callable: value, key map_filter(map{ a = 0, b = 1 }); // returns [map]{b=1} # map_process [function] == map_process( obj, callable ) === pass all items through a callable, return same object - 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 - More info about iterators: @"Iterator system" 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 - More info about iterators: @"Iterator system" 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 - More info about iterators: @"Iterator system" 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" - this function is equivalent to @sgs_GetBool / @sgs_ToBool in the C API tobool( 5 ); // returns 'true' tobool( "" ); // returns 'false' # toint [function] == toint( var ) === returns an integer, generated from variable `var` using the @"Conversion rules" - this function is equivalent to @sgs_GetInt / @sgs_ToInt in the C API 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" - this function is equivalent to @sgs_GetReal / @sgs_ToReal in the C API 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" - this function is equivalent to @sgs_ToString in the C API 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" - this function is equivalent to @sgs_GetPtr / @sgs_ToPtr in the C API 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 - this function is equivalent to @sgs_ParseInt in the C API 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 - this function is equivalent to @sgs_ParseReal in the C API 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/VT_THREAD - 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 - equivalent to @sgs_FindType in the C API 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 - this function is equivalent to @sgs_IsCallable in the C API 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' # 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_ext(var); calls for each argument - refer to @printvar_ext for more info # 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 # metaobj_set [function] == metaobj_set( object obj, object metaobj ) === sets the meta-object of an object # metaobj_get [function] == metaobj_get( object obj ) === retrieves the meta-object of an object # metamethods_enable [function] == metamethods_enable( object obj, bool enable ) === enables or disables metamethod support for an object # metamethods_test [function] == metamethods_test( object obj ) === retrieves metamethod support state # mm_getindex_router [function] == mm_getindex_router( key ) === __getindex to __get_*** router - when applied to metaobject of a metamethod-enabled object's `__getindex` property, it routes every request to `__get_` - see @Metamethods for more info # mm_setindex_router [function] == mm_setindex_router( key, value ) === __setindex to __set_*** router - when applied to metaobject of a metamethod-enabled object's `__setindex` property, it routes every request to `__set_` - see @Metamethods for more info # event [function] == event( bool signaled = false ) === Creates an event. - This object can be used to stop a thread. See @end_on for more info. - Event is initialized to the state specified by `signaled`. - This object consists of one property - `bool signaled`. It can be modified to change the state of the event. # pooled_event [function] == pooled_event( object, string name, bool signaled = false ) === Create a pooled event (named event, in table) - This object can be used to stop a thread. See @end_on for more info. - If the event is found in the object as a property by the given name, that event is returned instead, without modification. -- Otherwise, a new event is created and registered to the specified object as a property with the given name. - Event is initialized to the state specified by `signaled`. - This object consists of one property - `bool signaled`. It can be modified to change the state of the event. # end_on [function] == end_on( this thread, object event, bool enable = true ) === Set or unset an event object that can stop a thread. An "event" is any object that implements the "convert to bool" behavior. True means 'signaled', false - inactive. When the event is signaled, the thread will be aborted as soon as possible. - Alternatively accessible via the "end_on" property of any thread. - @sgs_EndOn is the C version of this function. # co_create [function] == co_create( callable ) === Creates a coroutine with the specified callable. - function returns a coroutine object that can be started/resumed with @co_resume # co_resume [function] == co_resume( coroutine[, args..] ) === Starts or resumes the coroutine. - if function is called for the first time, the attached callable is called within the coroutine, passing given arguments to the callable - if function is suspended, arguments will be passed as return values from the @yield call that suspended it # thread_create [function] == thread_create( fn, this[, args..] ) === Starts a managed topmost coroutine (thread). - This function returns the created thread. - The function passed is immediately called once. - This thread is owned by the topmost owned thread (engine thread or coroutine created with co_create) - if it's destroyed, this thread will be aborted and destroyed as well. # subthread_create [function] == subthread_create( fn, this[, args..] ) === Starts a managed sub-coroutine (subthread). - This function returns the created subthread. - The function passed is immediately called once. - This thread is owned by the current context (thread, subthread, engine thread or coroutine) - if it's destroyed, this thread will be aborted and destroyed as well. # process_threads [function] == process_threads( dt[, ctx ] ) === Advance the managed subthreads once, using the specified delta time. - If `ctx` is unspecified, it defaults to the current context. - This function should only be used on the engine thread and owned coroutines since it recursively advances all subthreads. # yield [function] == yield([ args.. ]) === Suspends the current state, returning to caller. - Arguments are passed as return values to the caller. - State cannot be suspended if there are C functions or other unusual constructs in the stack. # abort [function] == abort([ contexts... ]) === Stops execution and returns to C code as soon as possible. - If no contexts are specified, current context is aborted, otherwise only the specified contexts are aborted. - This function is equivalent to using @sgs_Abort in the C API. abort(); print( 5 ); // this line is not reached # 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 using the compatible function call syntax (`thisvar!func( arg1, ... )`) to this function. - C functions, SGS functions and closure objects 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: " assert( text, "text was not defined" ); # sym_register [function] == sym_register( string name, var ) === Register a persistent item (symbol) by the specified name. - Symbols are used for serialization to map unserializable and persistent items in both ways, to preserve their linkage in the serialized data. - This function is equivalent to @sgs_RegSymbol in the C API. myfunc = function(){}; sym_register( "myfunc", myfunc ); # sym_get [function] == sym_get( var ) === Map name to a registered variable or variable to name using the symbol table. - This function is equivalent to @sgs_GetSymbol in the C API. print sym_get( assert ); // prints "assert" print sym_get( "assert" ); // prints "C function" # eval [function] == eval( string code ) === returns the result of evaluating the passed `code` string as SGScript code - this function is equivalent to @sgs_EvalBuffer / @sgs_EvalString in the C API 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 - this function is equivalent to @sgs_EvalFile in the C API 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 # find_include_file [function] == find_include_file( string file ) === Find the include file according to SGS_PATH. - File is searched according to the semicolon-separated pattern list specified in the global variable `SGS_PATH`. -- `|` - replaced with calling file's directory. -- `@` - replaced with process directory. -- `?` - replaced with `file`. - A path to file is only returned if the file exists. # 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_curprocfile [function] == sys_curprocfile() === returns the path of the executable file the script is executed in - in case of failure, function will set errno # sys_curprocdir [function] == sys_curprocdir() === returns the path to the directory of the executable file the script is executed in # multiply_path_ext_lists [function] == multiply_path_ext_lists( string prefixes, string joiner = "/"[, string suffixes ]) === combines `prefixes` (paths) and `suffixes` (extensions) through the `joiner` string to create an array of paths - default value of `suffixes` is platform-specific and equal to the last logical half of the initial SGS_PATH value -- from code: `suffixes = "?;?" SGS_MODULE_EXT ";?.sgc;?.sgs"` (SGS_MODULE_EXT is either ".dll" or ".so") - `prefixes` and `suffixes` are expected to be in the SGS_PATH format - semicolon-separated (;) strings # 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 )` # 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 - last relevant error number is defined by @sgs_Errno / @sgs_SetErrno C API functions 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_msg( 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, int mode = 2 ) === 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, int mode = 2 ) === 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 - for more info, 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} # sgson_encode [function] == sgson_encode( var[, string tab ]) === Encodes the given variable in the SGSON format. - `tab` allows to specify the string used for tabs -- if `tab` is `null`, the text output is tightly packed, without any extra spaces # sgson_decode [function] == sgson_decode( string data ) === Decodes the SGSON text into a variable # SGS_*** [constants] == SGS_INFO, SGS_WARNING, SGS_ERROR, SGS_APIERR === defined to the values of the C macros, respectively 100, 200, 300 and 330 # VT_*** [constants] == VT_NULL, VT_BOOL, VT_INT, VT_REAL, VT_STRING, VT_FUNC, VT_CFUNC, VT_OBJECT, VT_PTR, VT_THREAD === 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 # _R [superglobal] == A hard-coded global value that points to the registry. Can be used to access the symbol table (_R["$sym"]) or include list (_R["$inc"]). - It is preferred to use @sym_get and @sym_register to deal with symbols, this table is mostly available for introspection and workarounds. # _F [superglobal] == The currently executed function. - It can be used in a function to call itself recursively, especially when the function is defined in a position where it cannot reference itself without additional effort. function f(){ printvar( _F ); } f(); // prints info about function 'f' # _T [superglobal] == The currently executed thread (context/coroutine). function f(){ printvar( _T ); } f(); // prints info about current context thread f(); // prints info about this newly created thread # array [object] - built-in methods -- @push -- @pop -- @shift -- @unshift -- @insert -- @erase -- @part -- @clear -- @reverse -- @resize -- @reserve -- @sort -- @sort_custom -- @sort_mapped -- @find -- @remove -- @unique -- @random -- @shuffle - 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 -- meta-object (global @array) # 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 ( + 1) to them -- beginning of array can be inserted to using position 0 or (- - 1) -- end of array can be inserted to using position 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") # ALL SGScript core functions (A-Z) [info] ~!~ render = list_pages_asc ~!~ filter_type = function,functions,function alias,function aliases # <<< # Formatting library ("fmt") [info] This library includes functions and objects for parsing binary and text buffers. - binary format -- @fmt_pack, @fmt_unpack, @fmt_pack_count, @fmt_pack_size - base64 format -- @fmt_base64_encode, @fmt_base64_decode - custom format -- @fmt_custom_encode - text format -- @fmt_parser, @fmt_text, @fmt_charcc === 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_custom_encode - encodes a custom format (selected character codes to numeric version) - @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 - decoding is done using the table mentioned in @fmt_base64_encode() fmt_base64_decode( fmt_base64_encode( "hello world" ) ) == "hello world" // returns true # fmt_custom_encode [function] == fmt_custom_encode( string text, string class, string prefix, int format, int mindigits = 0, string postfix = "" ) === encodes a custom format (selected character codes to numeric version) Every character (byte) from `text` that matches `class` is converted to the following format: - `prefix` - number according to `format`, at least `mindigits` long - `postfix` `format` must be one of: - `FMT_NUMBER_BINARY` - binary (base 2) number - `FMT_NUMBER_OCTAL` - octal (base 8) number - `FMT_NUMBER_DECIMAL` - decimal (base 10) number - `FMT_NUMBER_HEX`, `FMT_NUMBER_HEX_LC` - lowercase hexadecimal (base 16) number - `FMT_NUMBER_HEX_UC` - uppercase hexadecimal (base 16) number Use case example - encode a string for C/C++ source code output: // character class: // - '^' - invert class (exclude the following characters/ranges) // - , '!' - characters to exclude (first printable characters, before quote) // - '#-~' - character range to exclude (other printable characters, after quote) // the extra set of quotes around hex code prevent hyperactive parsers from thinking .. // .. that the following characters might be a part of the hex code fmt_custom_encode( 'some text', "^ !#-~", '""\\x', FMT_NUMBER_HEX, 2, '""' ) # 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]} -- 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: 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 -- @getchar -- @readcc -- @skipcc -- @read_real -- @read_int -- @read_binary_int -- @read_octal_int -- @read_decimal_int -- @read_hex_int -- @check - read-only properties -- [bool] at_end -- [bool] stream_offset - other features: -- GC-safe # 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) [info] ~!~ render = list_pages_asc ~!~ filter_type = function,functions,function alias,function aliases # <<< # I/O library ("io") [info] This library contains the functions necessary to work with the file system (files and directories). === Functions: - @io_setcwd - set the current working directory - @io_getcwd - returns the current working directory - @io_getexecpath - returns the absolute executable path - @io_rename - rename or move a file system item - @io_file_exists - returns whether the specified file exists and is accessible - @io_dir_exists - returns whether the specified directory exists and is accessible - @io_stat - returns information about a file system item - @io_dir_create - create a directory - @io_dir_delete - remove a directory - @io_file_delete - deletes a file - @io_file_write - writes byte buffer to file, creating or overwriting it, as necessary - @io_file_read - reads byte buffer from a file - @io_file - creates a @io_file object, optionally opening it - @io_dir - creates a @io_dir directory iterator object, set to read a specific directory === 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: - @FILE_*** - mode constants for @io_file.open / @"io_file [function]" - @SEEK_*** - mode constants for @io_file.seek - @FST_*** - file system item type constants for @io_stat # >>> # 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 -- @open -- @close -- @read -- @write -- @seek -- @flush -- @setbuf - 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 === mode constants for @io_file.open / @"io_file [function]" # 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) [info] ~!~ render = list_pages_asc ~!~ filter_type = function,functions,function alias,function aliases # <<< # Math library ("math") [info] 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) [info] ~!~ render = list_pages_asc ~!~ filter_type = function,functions,function alias,function aliases # <<< # OS library ("os") [info] # This function deals with data that can be retrieved from the operating system. This includes the following data sources: - environment variables - time and date - locale / regional settings === Functions: - @os_gettype - returns the name of closest known OS type match, defined at compile time - @os_command - pass command to OS command processor - @os_getenv - returns the value of the specified environment variable - @os_putenv - set an environment variable - @os_time - returns the time in seconds, optionally from a different time zone - @os_get_timezone - returns the time zone set in OS, optionally as string - @os_date_string - format a time value into a string - @os_parse_time - split time value into components - @os_make_time - make a time value from components - @os_get_locale - returns current locale of the specified category - @os_set_locale - set locale for the specified category - @os_get_locale_format - returns locale formatting info - @os_locale_strcmp - compare two strings using locale === Constants: - @LC_*** - locale categories # >>> # 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 "=" # os_time [function] == os_time( real tz = ) === 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 "%" -- %: 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) [info] ~!~ render = list_pages_asc ~!~ filter_type = function,functions,function alias,function aliases # <<< # Regular expression library ("re") [info] 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_RETURN_*** - flag constants for @re_match / @re_match_all # >>> # 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 --- each entry is same as in @re_match # 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) [info] ~!~ render = list_pages_asc ~!~ filter_type = function,functions,function alias,function aliases # <<< # String library ("string") [info] 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: - @string_utf8_iterator - UTF-8 code point iterator === 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 {:} 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) [info] ~!~ render = list_pages_asc ~!~ filter_type = function,functions,function alias,function aliases # <<< # <<< # Included tools [info] === Executables - @"Virtual Machine (sgsvm)" - @"Compiler (sgsc)" - @"Executable generator for Windows (sgsexe)" - @"Language test application (sgstest)" - @"API test application (sgsapitest)" - @"C++ binding compiler test application (sgscppbctest)" - @"Multithreading safety test application (mttest)" === Extensions - @"Profiler" - @"Interactive debugger" # >>> # Virtual Machine (sgsvm) [info] 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 [, ] === 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) [info] 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) [info] 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 # Language test application (sgstest) [info] 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) [info] 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) [info] This application tests the C++ programming interface that utilizes the @"binding compiler". # Multithreading safety test application (mttest) [info] This application tests the SGScript engine's ability to work with more than one thread (different instances for each) at the same time. # Profiler [info] 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 - void sgs_ProfInit( sgs_Context* C, sgs_Prof* P, int mode ) - initialize the profiler - void sgs_ProfClose( sgs_Prof* P ) - free the profiler - void sgs_ProfDump( sgs_Prof* P ) - 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 [info] 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_Context* C, SGS_IDBG ) - initialize the debugger - int sgs_CloseIDbg( sgs_Context* C, 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 ); # <<< # Additional info [info] # >>> # Serialization in SGScript [info] 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(Ext) / @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 (modes 1 and 2) - 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 following data differs between formats: --- MODE 1: number of arguments (4 bytes), function name length (1 byte) and the null-terminated function name itself (+1 bytes) --- MODE 2: number of arguments (4 bytes), function name length (1 byte), argument indices (4 bytes for each, count as previously specified) and the null-terminated function name itself (+1 bytes) === The format (mode 3) - SGScript Object Notation (SGSON) - a minimal version of the script syntax for defining data - Supported features: -- keywords: `null`, `false`, `true` -- integers and real values -- strings (`"..."` or `'...'`) -- containers: --- array: `[...]` --- dict: `{ a = 1, b = "x" }` --- map: `map{ [false] = 5, [{}] = "test" }` -- function calls: `(, , ... )` === Serialization - "@serialize" is called - "@sgs_Serialize(Ext)" is called internally - type of variable is determined and the data is written -- C functions cannot be serialized 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(Ext) 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'/'map' === Deserialization - "@unserialize" is called - "@sgs_Unserialize(Ext)" is called internally - "push", "call", "symbol" operations are executed, thus regenerating the data -- "push" operation pushes a variable on the stack -- "call" operation calls the specified function -- "symbol" operation resolves the given string to a variable from the symbol table === 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 temporarily replacing the global environment (_G) - if environment overrides are used on deserialization, remember to add "array", "dict" and "map" to the list if you use them, they are not always supported automatically - mode 1/3 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 use mode 2 (default) instead # Secure sandbox environment [info] 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): - core functions: -- @include_library - access to file system, can load other libraries -- @include_shared - access to file system, can run some library code -- @include_file - access to file system, can run script files -- @include - access to file system, can load other libraries, can run script files or some library code -- @import_cfunc - access to file system, can run some library code -- @eval_file - access to file system, can run script files - @"All functions in I/O library" - access to file system - @"OS library": -- @os_command - can run any terminal command == Information control (access to data about the system) - @"Most functions in OS library" - access to environment variables, system date/time info / process locale info. - core functions: -- @printvar, @printvar_ext, @dumpvar, @dumpvar_ext, @sys_stat, @toptr - access to memory layout of engine objects # <<<