The Sol Programming Language!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214 ``````#ifndef SOL_H #define SOL_H #ifndef NULL #define NULL ((void *) 0) #endif #include #include #include #include "dsl/dsl.h" /** The version of the project, as made available through `debug.version`. */ #define SOL_VERSION "0.5a4" /** The hexadecimal version of the project, formatted 0xAAIIRPP where: * * - AA is the two-digit major version * - II is the two-digit minor version * - R is 'A' for alpha, 'B' for beta, 'C' for candidate, and 'F' for final * - PP is the two-digit patch * * This value is guaranteed to only monotonically increase by revision, within * the same line of development. In particular, features introduced in some * version shall be available in all versions numerically greater than it * (unless they are later deprecated or removed). */ #define SOL_HEXVER 0x0005A04 #ifndef SOL_BUILD_HOST #define SOL_BUILD_HOST "(unknown host)" #endif #ifndef SOL_BUILD_KERNEL #define SOL_BUILD_KERNEL "(unknown kernel)" #endif #ifndef SOL_BUILD_ARCH #define SOL_BUILD_ARCH "(unknown arch)" #endif #ifndef SOL_BUILD_REV #define SOL_BUILD_REV "(unknown rev)" #endif #define SOL_BUILD_ID "sol " SOL_VERSION "-" SOL_BUILD_REV " " __DATE__ " " __TIME__ " on " SOL_BUILD_HOST " " SOL_BUILD_KERNEL " " SOL_BUILD_ARCH #ifndef SOL_ICACHE_MIN /** The smallest integer to cache. */ #define SOL_ICACHE_MIN -128 #endif #ifndef SOL_ICACHE_MAX /** The largest integer to cache. */ #define SOL_ICACHE_MAX 256 #endif #if !defined(SOL_ICACHE) && (SOL_ICACHE_MIN < SOL_ICACHE_MAX) #define SOL_ICACHE #endif // Forward declarations: struct sol_tag_object_t; typedef struct sol_tag_object_t sol_object_t; struct sol_tag_state_t; typedef struct sol_tag_state_t sol_state_t; /** CFunction type. * * This is the essential type for most C interface routines. It receives two * parameters: * * - The state under which the function is invoked, and * - A list object containing a set of parameters, which are generally * well-defined per location or operation. * * The function should return a new reference to an object. If the value is * unimportant or otherwise ignored, the canonical return value is * `sol_incref`(state->None). */ typedef sol_object_t *(*sol_cfunc_t)(sol_state_t *, sol_object_t *); /** Print function type. * * \rst * .. admonition:: Deprecated * * This is not used anywhere and is likely to be removed in the * near future. * \endrst */ typedef void (*sol_printfunc_t)(sol_object_t *); /** Type methods structure. * * Sol bases most of its object behavior on methods defined on so-called "ops * structures" of this type pointed to by the objects themselves. In general, * these contain the address of one such structure stored directly in the state * (each state has its own set of these structures for all the builtin types, * initialized in `sol_state_init`), but they can conceivably be allocated and * initialized elsewhere, e.g., in extension modules. * * Nearly all of the fields in this structure are function pointers to * `sol_cfunc_t` that are called when an operator is invoked on an object. In * the case of binary operators, only the left operand is considered. * * In member documentation of these functions, the list [in brackets] * represents, visually, the list that the function can expect to receive as * the second argument (where "rhs" is right-hand-side of a binary operator, * and "this" is the object whose ops structure was indexed). Note that the * runtime does not use nor take advantage of the returns of all of these * methods. */ typedef struct { /** A C-string naming the type, for use by the built-in `type` function. */ char *tname; /** Some type-specific flags for this type. */ unsigned short tflags; /** Called with [this, rhs] to perform binary addition ("+"). */ sol_cfunc_t add; /** Called with [this, rhs] to perform binary subtraction ("-"). */ sol_cfunc_t sub; /** Called with [this, rhs] to perform binary multiplication ("*"). */ sol_cfunc_t mul; /** Called with [this, rhs] to perform binary division ("/"). */ sol_cfunc_t div; /** Called with [this, rhs] to perform binary modulus ("%"). */ sol_cfunc_t mod; /** Called with [this, rhs] to perform binary exponentiation ("**"). */ sol_cfunc_t pow; /** Called with [this, rhs] to perform the triple-bang operation ("!!!"), defaults to identity-swapping two objects. */ sol_cfunc_t tbang; /** Called with [this, rhs] to perform binary bitwise AND ("&") */ sol_cfunc_t band; /** Called with [this, rhs] to perform binary bitwise OR ("|") */ sol_cfunc_t bor; /** Called with [this, rhs] to perform binary bitwise XOR ("^") */ sol_cfunc_t bxor; /** Called with [this, rhs] to perform binary bitwise left shift ("<<") */ sol_cfunc_t blsh; /** Called with [this, rhs] to perform binary bitwise right shift (">>") */ sol_cfunc_t brsh; /** Called with [this] to perform bitwise not ("~") */ sol_cfunc_t bnot; /** Called with [this, rhs] to perform comparison; the result should be an integer object of value -1 (this < rhs), 0 (this == rhs), or 1 (this > rhs) */ sol_cfunc_t cmp; /** Called with [this, arg1, arg2, ...] to perform a call (as "this(arg1, arg2, ...)") */ sol_cfunc_t call; /** Called with [this, index] to perform an index like "this[index]" or "this.index" (in the latter, index will be a string object) */ sol_cfunc_t index; /** Called with [this, index, value] to perform a setindex (like "this[index] = value" or "this.index = value" for index being a string object) */ sol_cfunc_t setindex; /** Called with [this] to perform a length predicate (like "#this") */ sol_cfunc_t len; /** Called with [this] to return a function object (or cfunction object) that will iterate over "this" (see the iterator protocol for more details) */ sol_cfunc_t iter; /** Called with [this] to cast "this" to an integer object. This may raise an error, which should be checked. */ sol_cfunc_t toint; /** Called with [this] to cast "this" to a float object. This may raise an error, which should be checked. */ sol_cfunc_t tofloat; /** Called with [this] to cast "this" to a string object. This generally shouldn't raise an error, and usually falls back to a simple representation. */ sol_cfunc_t tostring; /** Called with [this] to cast "this" to a buffer object. This generally shouldn't raise an error, and usually falls back to converting the tostring to a buffer (which might be lossy if the string has embedded NULs). */ sol_cfunc_t tobuffer; /** Called with [this] to provide a representation of "this", in the sense that it is human-readable and informative. This usually falls back to tostring. */ sol_cfunc_t repr; /** Called with this (*not a list*) as a result of calling `sol_init_object`. Since this is usually called from a constructor anyway, it's usually fairly useless. It should return this. */ sol_cfunc_t init; /** Called with this (*not a list*) and *with a NULL state* before an object is freed; it should free any resources this object exclusively holds, and return this. */ sol_cfunc_t free; } sol_ops_t; /** Don't eval arguments passed to ops->call; you will get AST expr_nodes * instead (wrapped up in SOL_EXPR objects). Call sol_eval to evaluate them when * desired. */ #define SOL_TF_NO_EVAL_CALL_ARGS 1 /** Object types known to Sol. * * This is rarely checked and generally only used where necessary, as there is * no way to extend this list naturally for an extension developer. * * For each of these types, there is almost certainly a test macro for it. */ typedef enum { /** The singlet type--the type of None, as well as OutOfMemory. It is also the "default" type. */ SOL_SINGLET, /** The integer type, implemented as a long. */ SOL_INTEGER, /** The floating point type, implemented as a double. */ SOL_FLOAT, /** The string type, implemented as a C string. */ SOL_STRING, /** The list type, implemented as a DSL sequence of object pointers. */ SOL_LIST, /** The map type, implemented as a DSL sequence of MCELL object pointers arranged as an associative array.. */ SOL_MAP, /** The mcell type, a simple key-value pair only to be found in a map. */ SOL_MCELL, /** The function type, the type of all user-defined functions in Sol. */ SOL_FUNCTION, /** The macro type, the type of all user-defined macros in Sol. */ SOL_MACRO, /** The cfunction type, the type of objects wrapping a `sol_cfunc_t`. */ SOL_CFUNCTION, /** The cfunction type, the type of objects wrapping a `sol_cfunc_t` without evaluating their arguments. */ SOL_CMACRO, /** The statement type, the type of objects wrapping a `stmt_node`. */ SOL_STMT, /** The expression type, the type of objects wrapping an `expr_node`. */ SOL_EXPR, /** The buffer type, a type designed to access arbitrary memory. */ SOL_BUFFER, /** The dylib type, the type of dynamically-loaded shared libraries. */ SOL_DYLIB, /** The dysym type, the type of symbols resolved in dylib objects. */ SOL_DYSYM, /** The stream type, the type wrapping FILE *. */ SOL_STREAM, /** The cdata type, the type used for extension by various modules. */ SOL_CDATA } sol_objtype_t; /** Buffer types. * * These types indicate what a buffer or subsection of a buffer may refer to. */ typedef enum { /** The region is typeless. This is the default, and prohibits access unless it is retyped. */ BUF_NONE, /** The region contains an 8-bit signed integer. */ BUF_INT8, /** The region contains a 16-bit signed integer. */ BUF_INT16, /** The region contains a 32-bit signed integer. */ BUF_INT32, /** The region contains a 64-bit signed integer. */ BUF_INT64, /** The region contains an 8-bit unsigned integer. */ BUF_UINT8, /** The region contains a 16-bit unsigned integer. */ BUF_UINT16, /** The region contains a 32-bit unsigned integer. */ BUF_UINT32, /** The region contains a 64-bit unsigned integer. */ BUF_UINT64, /** The region contains an ASCII character. */ BUF_CHAR, /** The region contains exactly one addressable unit. */ BUF_BYTE, /** The region contains a platform-sized signed integer. */ BUF_INT, /** The region contains a platform-sized unsigned integer. */ BUF_UINT, /** The region contains a platform-sized signed long integer. */ BUF_LONG, /** The region contains a platform-sized unsigned long integer. */ BUF_ULONG, /** The region contains a platform single-precision floating point. */ BUF_FLOAT, /** The region contains a platform double-precision floating point. */ BUF_DOUBLE, /** The region contains a pointer to a NUL-terminated C string. */ BUF_CSTR, /** The region contains a generic pointer (which will instantiate another buffer). */ BUF_PTR } sol_buftype_t; /** Ownership types. * * These functions determine what happens to the memory region aliased by a * buffer when that object is freed or copied. */ typedef enum { /** Nothing happens; the object is freed or copied normally. */ OWN_NONE, /** The libc `free` function is called on the buffer. Nothing happens when a new buffer is made to alias it. */ OWN_FREE, /** The movefunc and freefunc are respectively consulted. */ OWN_CALLF } sol_owntype_t; /** * Transput modes. * * These constants are defined (by the same name) on the `io` module as valid bits for the second argument to `io.open`. */ typedef enum { /** Permit reading. If this is not set, any attempt to read will raise an error. */ MODE_READ = 1, /** Permit writing. If this is not set, any attempt to write will raise an error. */ MODE_WRITE = 2, /** When opening for writing, direct all writes to the end of the file. This has no effect on read positions, when opened in both modes. */ MODE_APPEND = 4, /** When opened for writing, truncate the file to zero size. Previous contents are lost. */ MODE_TRUNCATE = 8, /** Prepare the file for reading or writing binary data as opposed to text. */ MODE_BINARY = 16 } sol_modes_t; /** Buffer freeing function. * * This is called with the buffer region and given size when a buffer object is * freed (from state.BufferOps.free) when the `sol_owntype_t` is set to * `OWN_CALLF`. It should do whatever is needed to release this one alias of * memory. Note that care should be taken if multiple buffer objects alias the * same region. */ typedef void (*sol_freefunc_t)(void *, size_t); /** Buffer moving function. * * This is called with the buffer region and given size when a buffer object is * somehow copied (usually by dereferencing a `BUF_PTR`). It should return the * region that the new buffer object should refer to. The size is assumed to * not change. */ typedef void *(*sol_movefunc_t)(void *, size_t); /** Object structure. * * This structure defines the interface of every Sol object. Just as well (and * as an implementation detail), it contains the operative members of every * built-in type. */ typedef struct sol_tag_object_t { /** The type of this object. */ sol_objtype_t type; /** The number of living references to this object, increased by `sol_incref` and decreased by `sol_obj_free`. */ int refcnt; /** The ops structure defining the behavior of this object under certain operations (more or less, its behavioral "type"). */ sol_ops_t *ops; union { /** For `SOL_INTEGER`, the value of the integer. */ long ival; /** For `SOL_FLOAT`, the value of the floating point number. */ double fval; /** For `SOL_STRING`, the C string pointer. For `SOL_SINGLET`, the name of this singlet. */ char *str; /** For `SOL_LIST` and `SOL_MAP`, the DSL sequence that contains the items or pairs. */ dsl_seq *seq; struct { /** For `SOL_MCELL`, the key of the pair. */ struct sol_tag_object_t *key; /** For `SOL_MCELL`, the value of the pair. */ struct sol_tag_object_t *val; }; struct { /** For `SOL_FUNCTION`, the `stmt_node` pointer representing the function's body. */ void *func; // Actually a stmt_node * /** For `SOL_FUNCTION`, the `identlist_node` pointer representing the list of the functions argument names. */ void *args; // Actually an identlist_node * /** For `SOL_FUNCTION`, a map representing the closure (initial scope, updated on exit) of the function. */ struct sol_tag_object_t *closure; /** For `SOL_FUNCTION`, a map of data defined by the user on this function object. */ struct sol_tag_object_t *udata; /** For `SOL_FUNCTION`, the name of the function if it was not declared anonymously (otherwise NULL). */ char *fname; /** For `SOL_FUNCTION`, the name of an argument that receives extra parameters as a list (otherwise NULL). */ char *rest; /** For `SOL_FUNCTION`, the map of annotations, with arguments by name, and the function itself by object. */ struct sol_tag_object_t *annos; }; struct { /** For `SOL_CFUNCTION`, the C function pointer. */ sol_cfunc_t cfunc; /** For `SOL_CFUNCTION`, the name of this function, or NULL. */ char *cfname; }; /** For `SOL_STMT` and `SOL_EXPR`, the `stmt_node` or `expr_node` pointer, respectively. */ void *node; struct { /** For `SOL_BUFFER`, the memory region referred to by this buffer. */ void *buffer; /** For `SOL_BUFFER`, the size of this memory region. Negative values indicate no or unknown size. */ ssize_t sz; /** For `SOL_BUFFER`, the ownership type of this buffer's region. */ sol_owntype_t own; /** For `SOL_BUFFER`, the freeing function if own == `OWN_CALLF` */ sol_freefunc_t freef; /** For `SOL_BUFFER`, the moving function if own == `OWN_CALLF` */ sol_movefunc_t movef; }; /** For `SOL_DYLIB`, the handle as returned by `dlopen`. */ void *dlhandle; struct { /** For `SOL_DYSYM`, the symbol as resolved by `dlsym`. */ void *dlsym; /** For `SOL_DYSYM`, a sequence of the types of the arguments (a set of `sol_buftype_t` cast to void *, the native type of DSL), if the symbol is a function. */ dsl_seq *argtp; /** For `SOL_DYSYM`, the return type of the symbol if it is a function; otherwise, the type of the symbol if it is a variable. */ sol_buftype_t rettp; }; struct { /** For `SOL_STREAM`, the actual file object. */ FILE *stream; /** For `SOL_STREAM`, the modes for which this stream is open. */ sol_modes_t modes; }; /** For `SOL_CDATA`, an arbitrary, user-defined pointer. */ void *cdata; }; } sol_object_t; /** State flags. * * These flags get set during execution and indicate an altered state of * interpretation (other than the altered state of interpretation that comes * about due to an error propagation). */ typedef enum {SF_NORMAL, SF_BREAKING, SF_CONTINUING} sol_state_flag_t; typedef struct sol_tag_state_t { sol_object_t *scopes; ///< A list of scope maps, innermost out, ending at the global scope sol_object_t *ret; ///< Return value of this function, for early return sol_object_t *traceback; ///< The last stack of statement (nodes) in the last error, or NULL sol_object_t *fnstack; ///< The stack of function objects (`SOL_FUNCTION`, `SOL_CFUNCTION`) in the current call stack jmp_buf topfunc; ///< A jump buffer pointing to the most recent `SOL_FUNCTION` call, used for tail calls sol_object_t *topargs; ///< The new arguments passed before jumping in a tail call sol_state_flag_t sflag; ///< Used to implement break/continue sol_object_t *error; ///< Some arbitrary error descriptor, `None` if no error sol_object_t *_stdout; ///< Standard output stream object (for print(), type `SOL_STREAM`) sol_object_t *_stdin; ///< Standard input stream object (type `SOL_STREAM`) sol_object_t *_stderr; ///< Standard error stream object (type `SOL_STREAM`) sol_object_t *None; ///< The all-important `None` object sol_object_t *OutOfMemory; ///< The semi-important `OutOfMemory` object sol_ops_t NullOps; ///< Basic, initialized operations. Not used by any extant object type. sol_ops_t SingletOps; ///< Operations on singlets (`None`, `OutOfMemory`, etc.) sol_ops_t IntOps; ///< Operations on integers sol_ops_t FloatOps; ///< Operations on floats sol_ops_t StringOps; ///< Operations on strings sol_ops_t ListOps; ///< Operations on lists sol_ops_t MapOps; ///< Operations on maps sol_ops_t MCellOps; ///< Operations on map cells (rarely used) sol_ops_t FuncOps; ///< Operations on functions sol_ops_t MacroOps; ///< Operations on macros sol_ops_t CFuncOps; ///< Operations on C functions sol_ops_t CMacroOps; ///< Operations on C macros sol_ops_t ASTNodeOps; ///< Operations on AST nodes sol_ops_t BufferOps; ///< Operations on buffers sol_ops_t DyLibOps; ///< Operations on dynamic library objects sol_ops_t DySymOps; ///< Operations on dynamic symbol objects sol_ops_t StreamOps; ///< Operations on streams sol_object_t *modules; ///< A map of modules, string name to contents, resolved at "super-global" scope (and thus overrideable) sol_object_t *methods; ///< A map of string names to methods (like "list" -> {insert=, remove=, ...}) free for private use by extension developers dsl_object_funcs obfuncs; ///< The set of object functions that allows DSL to integrate with Sol's reference counting const char *calling_type; ///< Set (during `CALL_METHOD`) to determine the type (ops structure) being invoked for this method (mostly for sol_f_not_impl) const char *calling_meth; ///< Set (during `CALL_METHOD`) to determine the method name being invoked (mostly for sol_f_not_impl) #ifdef SOL_ICACHE sol_object_t *icache[SOL_ICACHE_MAX - SOL_ICACHE_MIN + 1]; ///< The integer cache (holds integers from `SOL_ICACHE_MIN` to `SOL_ICACHE_MAX` indexed by `[i - SOL_ICACHE_MIN]`) char icache_bypass; ///< Set to true to bypass caching--needed to avoid infinite recursion when initially populating the cache #endif sol_object_t *lastvalue; ///< Holds the value of the last expression evaluated, returned by an `if` expression sol_object_t *loopvalue; ///< Holds an initially-empty list appended to by `continue ` or set to another object by `break ` unsigned short features; ///< A flag field used to control the Sol initialization processs } sol_state_t; /** Don't run user initialization files. */ #define SOL_FT_NO_USR_INIT 0x0001 /** Be noisy in the language runtime. */ #define SOL_FT_DEBUG 0x0002 // state.c #define SOL_PATH_ARRAY_SIZE 8 extern char *sol_AbsInitPaths[SOL_PATH_ARRAY_SIZE]; extern char *sol_HomeInitPaths[SOL_PATH_ARRAY_SIZE]; /** Initializes the state. * * This should be called once (and only once!) for every state; it does the important * work of ensuring that the state is ready to execute code, including: * * - Creating the initial singlet values `None` and `OutOfMemory`, * - Creating and populating the operations on all internally-defined object types. * - Initializing all built-in modules and methods. * - Running any "init.sol" files. * - Recognizing early-init errors and aborting. * * It is the singular, monolithic place where most pre-execution occurs, and language * developers may thus use it at their discretion. Extension developers should provide * their own documented initializers, and embedders should do their own initialization * immediately after calling this function. */ int sol_state_init(sol_state_t *); /** Cleans up the state. * * In theory, after calling this, the state should be ready to be released (e.g., freed * if it was allocated on the heap). Importantly, it should NOT be used for any code * execution after this call (it WILL segfault). */ void sol_state_cleanup(sol_state_t *); /** Resolve a name. * * Technically, a "name" can be anything (any key in a map, more precisely), but the * runtime (and most sane code) generally depends on names being strings. It is, however, * emphatically possible to populate the scopes with non-string names--for potential use * cases, see `programs/monty.sol` */ sol_object_t *sol_state_resolve(sol_state_t *, sol_object_t *); /** Resolve a string name, given as a C string. * * This handles the popular case where a C program would like to resolve the value of a * variable by (string) name. In particular, it handles the memory of doing so properly. */ sol_object_t *sol_state_resolve_name(sol_state_t *, const char *); /** Assign to a global name. * * This is rarely used, except in `sol_state_init`. It sets the value of the given name * (as an object) in the global (outermost) scope. Code execution generally uses the * local scope instead. */ void sol_state_assign(sol_state_t *, sol_object_t *, sol_object_t *); /** Assign to a global string name, given as a C string. * * This is a convenience for `sol_state_assign`, which handles the creation and destruction * of the Sol string. */ void sol_state_assign_name(sol_state_t *, const char *, sol_object_t *); /** Assign to a local name. * * Sets the name to the value in the local (innermost) scope. It has the functional equivalent * of the Sol code ` = ` in whatever context the state is in. */ void sol_state_assign_l(sol_state_t *, sol_object_t *, sol_object_t *); /** Assign to a local string name, given as a C string. * * Another convenience for `sol_state_assign_l`. */ void sol_state_assign_l_name(sol_state_t *, const char *, sol_object_t *); /** Push a scope. * * This adds a new (more-local) scope to the scope stack (`state->scopes`). This permits values * in such a scope to be manipulated independently of those in enclosing scopes, and their references * are discarded during the next `sol_state_pop_scope`. (The values may, of course, be present via * other references.) * * Scope stack manipulation MUST be balanced; egregious errors will occur otherwise. * * Scope stack manipulation is generally only necessary where another environment is expected for the * code running in that context; e.g., the body of a function, or an AST node from an imported file. In * particular, most control structures do NOT introduce scopes, due to the deleterious effects of having * no direct influence on enclosing scopes. */ void sol_state_push_scope(sol_state_t *, sol_object_t *); /** Pops a scope. * * Removes and discards the local scope. All names and associated value references are lost. * * This MUST be balanced with `sol_state_push_scope`. */ sol_object_t *sol_state_pop_scope(sol_state_t *); /** Returns the current error. * * This object is `None` if there is no error. See `sol_has_error`. */ sol_object_t *sol_get_error(sol_state_t *); /** Set the current error. * * Sets the current error object. Clears the error if the object is `None`. * * Returns a new reference to `None`, suitable for returning elsewhere. */ sol_object_t *sol_set_error(sol_state_t *, sol_object_t *); /** Set the current error to a string, given a C string. * * Conveniently sets the error to a string object created from the given C string. */ sol_object_t *sol_set_error_string(sol_state_t *, const char *); /** Clear the current error. * * Equivalent to `sol_set_error(state, state->None)`. */ void sol_clear_error(sol_state_t *); /** Prepares a traceback. * * Initializes the traceback stack to an empty list in preparation of `sol_add_traceback`. * Typically used by the runtime while recovering from an error; the value is ultimately * returned as the third element of the return list from `try`. */ void sol_init_traceback(sol_state_t *); /** Adds an object to a traceback. * * This object is usually an ASTNode; typically, it is a statement which was being executed * when the relevant error occurred. This object is made the first item of the traceback pair * (the second element is the current local scope). */ void sol_add_traceback(sol_state_t *, sol_object_t *); /** Gets the traceback. * * This will be a list of traceback pairs; each such pair will be [, * ]. */ sol_object_t *sol_traceback(sol_state_t *); /** Registers a module. * * Creates a module entry by name, referring to its value. Modules resolve after globals, and * therefore form a sort of untouchable "super-global" scope. Most built-in modules reside in * this namespace. */ void sol_register_module(sol_state_t *, sol_object_t *, sol_object_t *); /** Registers a module by string name, given a C string. * * A convenience for `sol_register_module`. */ void sol_register_module_name(sol_state_t *, char *, sol_object_t *); /** Gets a module. * * Retrieves a module by its given name. Its value will be as it was registered. */ sol_object_t *sol_get_module(sol_state_t *, sol_object_t *); /** Gets a module by string name, given a C string. * * A convenience for `sol_get_module`. */ sol_object_t *sol_get_module_name(sol_state_t *, char *); /** Registers methods. * * Creates a methods entry by name, referring to its value. Methods are never resolved directly * by (non-debug) code, but are used liberally throughout the C interface for implementing named * methods on objects (such as lists, buffers, etc.) that wouldn't normally resolve names--thus * the name. Thus, the mapping forms a sort of private namespace that may freely be used by * developers as they see fit. */ void sol_register_methods(sol_state_t *, sol_object_t *, sol_object_t *); /** Registers a method by string name, given a C string. * * A convenience for `sol_register_methods`. */ void sol_register_methods_name(sol_state_t *, char *, sol_object_t *); /** Gets methods. * * Retrieves the methods by its name, returning the value that was registered. */ sol_object_t *sol_get_methods(sol_state_t *, sol_object_t *); /** Gets methods by string name, given a C string. * * A convenience for `sol_get_methods`. */ sol_object_t *sol_get_methods_name(sol_state_t *, char *); /** Index operation override for the `io` module. * * This hook virtually provides `stdin`, `stdout`, and `stderr` by returning the relevant * values on the states. */ sol_object_t *sol_f_io_index(sol_state_t *, sol_object_t *); /** Setindex operation override for the `io` module. * * This hook intercepts and specially handles attempts to set `stdin`, `stdout`, and `stderr` * by setting the relevant values on the state. */ sol_object_t *sol_f_io_setindex(sol_state_t *, sol_object_t *); /** Retrieves the stdin stream. * * Returns the stream object used to read program input. */ sol_object_t *sol_get_stdin(sol_state_t *); /** Retrieves the stdout stream. * * Returns the stream object used to write program output. */ sol_object_t *sol_get_stdout(sol_state_t *); /** Retrieves the stderr stream. * * Returns the stream object used to write program errors or out-of-band data. */ sol_object_t *sol_get_stderr(sol_state_t *); /** Initializes an ops structure. * * This sets all the fields of a `sol_ops_t` to their sensible defaults. Such an initialized * structure is available on the state as `state->NullOps`. */ void sol_ops_init(sol_ops_t *); // builtins.c /** Not implemented handler. * * This raises the "Undefined method" error. */ sol_object_t *sol_f_not_impl(sol_state_t *, sol_object_t *); /** !!! handler. * * Swaps objects by value. */ sol_object_t *sol_f_tbang(sol_state_t *, sol_object_t *); /** No operation handler. * * Does nothing. */ sol_object_t *sol_f_no_op(sol_state_t *, sol_object_t *); /** Default comparison handler. * * Returns 0 (equal) if the references refer to exactly the same object, or * 1 (greater) otherwise. * * Note that this is not a partial order. */ sol_object_t *sol_f_default_cmp(sol_state_t *, sol_object_t *); /** Default tostring handler. * * Returns a string formatted as "< object at