mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-12-04 22:46:31 +00:00
Compare commits
7 Commits
1544332b90
...
f51e072922
Author | SHA1 | Date | |
---|---|---|---|
f51e072922 | |||
b66858d286 | |||
34c55eee87 | |||
a2d0b79c2e | |||
4de274d760 | |||
074e8b52cc | |||
56161a32e7 |
2
Makefile
2
Makefile
@ -1,7 +1,7 @@
|
|||||||
# make clean && make && ./bin/cosmo
|
# make clean && make && ./bin/cosmo
|
||||||
|
|
||||||
CC=clang
|
CC=clang
|
||||||
CFLAGS=-fPIE -Wall -Isrc -O3 -std=c99 #-g -fsanitize=address
|
CFLAGS=-fPIE -Wall -Isrc -O3 #-g -fsanitize=address
|
||||||
LDFLAGS=-lm #-fsanitize=address
|
LDFLAGS=-lm #-fsanitize=address
|
||||||
OUT=bin/cosmo
|
OUT=bin/cosmo
|
||||||
|
|
||||||
|
@ -59,7 +59,12 @@ Includes functions that interact with the operating system.
|
|||||||
|
|
||||||
| Name | Type | Behavior | Example |
|
| Name | Type | Behavior | Example |
|
||||||
| ------------ | ------------------------------------------------ | ------------------------------------------------------------------------ | ------------------------ |
|
| ------------ | ------------------------------------------------ | ------------------------------------------------------------------------ | ------------------------ |
|
||||||
| os.read | `(path<string>)` -> `<string>` or `<nil>` | Returns a file's contents or nil if it doesn't exist/an error occurred | `os.read("path")` -> `Hello, World!`|
|
| os.open | `(path<string>)` -> `<bool>, <obj>` | Opens a file at `path` and returns a file object. If the file does not exist, it will be created. | `os.open("test.txt")` -> `true, <file>` |
|
||||||
| os.time | `()` -> `<number>` | Returns the system time in Epoch format | `os.time()` -> `1.61691e+09` |
|
| os.time | `()` -> `<number>` | Returns the system time in Epoch format | `os.time()` -> `1.61691e+09` |
|
||||||
| os.system | `(cmd<string>)` -> `<number>` | Runs a system command as if it were a terminal and returns the exit code | `os.system("mkdir test")` -> `0` |
|
| os.system | `(cmd<string>)` -> `<number>` | Runs a system command as if it were a terminal and returns the exit code | `os.system("mkdir test")` -> `0` |
|
||||||
> -> means 'returns'
|
> -> means 'returns'
|
||||||
|
|
||||||
|
File objects have the following methods:
|
||||||
|
| Name | Type | Behavior | Example |
|
||||||
|
| ------------ | ------------------------------------------------ | ------------------------------------------------------------------------ | ------------------------ |
|
||||||
|
| file:read | `(amt<number> or "a")` -> `<string>` | Reads `amt` bytes from the file and returns them as a string. If `"a"` is passed, the entire file is read. | `file:read("a")` -> `"Hello world!"` |
|
9
examples/reader.cosmo
Normal file
9
examples/reader.cosmo
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
local err, file = os.open("LICENSE.md")
|
||||||
|
print("made file")
|
||||||
|
if err then
|
||||||
|
print("failed to open file")
|
||||||
|
end
|
||||||
|
|
||||||
|
print(file)
|
||||||
|
print(file:read("a"))
|
4
main.c
4
main.c
@ -75,7 +75,7 @@ static void repl(CState *state)
|
|||||||
cosmoV_pushString(state, "input");
|
cosmoV_pushString(state, "input");
|
||||||
cosmoV_pushCFunction(state, cosmoB_input);
|
cosmoV_pushCFunction(state, cosmoB_input);
|
||||||
|
|
||||||
cosmoV_register(state, 2);
|
cosmoV_addGlobals(state, 2);
|
||||||
|
|
||||||
while (_ACTIVE) {
|
while (_ACTIVE) {
|
||||||
if (!(line = linenoise("> "))) { // better than gets()
|
if (!(line = linenoise("> "))) { // better than gets()
|
||||||
@ -130,7 +130,7 @@ static bool runFile(CState *state, const char *fileName)
|
|||||||
cosmoV_pushString(state, "input");
|
cosmoV_pushString(state, "input");
|
||||||
cosmoV_pushCFunction(state, cosmoB_input);
|
cosmoV_pushCFunction(state, cosmoB_input);
|
||||||
|
|
||||||
cosmoV_register(state, 1);
|
cosmoV_addGlobals(state, 1);
|
||||||
|
|
||||||
ret = interpret(state, script, fileName);
|
ret = interpret(state, script, fileName);
|
||||||
|
|
||||||
|
178
src/cbaselib.c
178
src/cbaselib.c
@ -69,7 +69,7 @@ int cosmoB_pcall(CState *state, int nargs, CValue *args)
|
|||||||
bool res = cosmoV_pcall(state, nargs - 1, 1);
|
bool res = cosmoV_pcall(state, nargs - 1, 1);
|
||||||
|
|
||||||
// insert false before the result
|
// insert false before the result
|
||||||
cosmo_insert(state, 0, cosmoV_newBoolean(res));
|
cosmoV_insert(state, 0, cosmoV_newBoolean(res));
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ int cosmoB_loadstring(CState *state, int nargs, CValue *args)
|
|||||||
CObjString *str = cosmoV_readString(args[0]);
|
CObjString *str = cosmoV_readString(args[0]);
|
||||||
bool res = cosmoV_compileString(state, str->str, "");
|
bool res = cosmoV_compileString(state, str->str, "");
|
||||||
|
|
||||||
cosmo_insert(state, 0, cosmoV_newBoolean(res));
|
cosmoV_insert(state, 0, cosmoV_newBoolean(res));
|
||||||
return 2; // <boolean>, <closure> or <error>
|
return 2; // <boolean>, <closure> or <error>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ void cosmoB_loadLibrary(CState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// register all the pushed c functions and the strings as globals
|
// register all the pushed c functions and the strings as globals
|
||||||
cosmoV_register(state, i);
|
cosmoV_addGlobals(state, i);
|
||||||
|
|
||||||
// load other libraries
|
// load other libraries
|
||||||
cosmoB_loadObjLib(state);
|
cosmoB_loadObjLib(state);
|
||||||
@ -230,52 +230,129 @@ COSMO_API void cosmoB_loadObjLib(CState *state)
|
|||||||
cosmoV_registerProtoObject(state, COBJ_OBJECT, obj);
|
cosmoV_registerProtoObject(state, COBJ_OBJECT, obj);
|
||||||
|
|
||||||
// register "object" to the global table
|
// register "object" to the global table
|
||||||
cosmoV_register(state, 1);
|
cosmoV_addGlobals(state, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================================================================ [OS.*]
|
// ================================================================ [OS.*]
|
||||||
|
|
||||||
// os.read()
|
int fileB_read(CState *state, int nargs, CValue *args)
|
||||||
int cosmoB_osRead(CState *state, int nargs, CValue *args)
|
|
||||||
{
|
{
|
||||||
|
if (nargs != 2) {
|
||||||
|
cosmoV_error(state, "file:read() expected 2 arguments, got %d!", nargs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cosmoV_isValueUserType(state, args[0], COSMO_USER_FILE)) {
|
||||||
|
cosmoV_typeError(state, "file:read()", "<file>, <number> or \"a\"", "%s, %s",
|
||||||
|
cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
CObjObject *fileObj = cosmoV_readObject(args[0]);
|
||||||
|
FILE *file = cosmoO_getUserP(fileObj);
|
||||||
|
|
||||||
|
if (IS_NUMBER(args[1])) {
|
||||||
|
cosmo_Number length = cosmoV_readNumber(args[1]);
|
||||||
|
|
||||||
|
// make sure the length is within the bounds of the file
|
||||||
|
if (length < 0) {
|
||||||
|
cosmoV_error(state, "file:read() expected length to be >= 0, got %d!", length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate a buffer for the read data
|
||||||
|
char *buffer = cosmoM_xmalloc(state, length + 1);
|
||||||
|
|
||||||
|
// read the data
|
||||||
|
fread(buffer, sizeof(char), length, file);
|
||||||
|
|
||||||
|
// push the read data
|
||||||
|
CValue temp = cosmoV_newRef(cosmoO_takeString(state, buffer, length));
|
||||||
|
cosmoV_pushValue(state, temp);
|
||||||
|
} else if (IS_STRING(args[1])) {
|
||||||
|
if (strcmp(cosmoV_readCString(args[1]), "a") == 0) {
|
||||||
|
// get the length of the file
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
long length = ftell(file);
|
||||||
|
fseek(file, 0, SEEK_SET);
|
||||||
|
|
||||||
|
// allocate a buffer for the read data
|
||||||
|
char *buffer = cosmoM_xmalloc(state, length + 1);
|
||||||
|
|
||||||
|
// read the data
|
||||||
|
fread(buffer, sizeof(char), length, file);
|
||||||
|
|
||||||
|
buffer[length] = '\0'; // write the NULL terminator
|
||||||
|
|
||||||
|
// push the read data
|
||||||
|
CValue temp = cosmoV_newRef(cosmoO_takeString(state, buffer, length));
|
||||||
|
cosmoV_pushValue(state, temp);
|
||||||
|
} else {
|
||||||
|
cosmoV_error(state, "file:read() expected \"a\" or <number>, got %s!",
|
||||||
|
cosmoV_readCString(args[1]));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cosmoV_typeError(state, "file:read()", "<file>, <number> or \"a\"", "%s, %s",
|
||||||
|
cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fileB_gc(CState *state, int nargs, CValue *args) {
|
||||||
if (nargs != 1) {
|
if (nargs != 1) {
|
||||||
cosmoV_error(state, "os.read() expected 1 argument, got %d!", nargs);
|
cosmoV_error(state, "file:read() expected 1 argument, got %d!", nargs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cosmoV_isValueUserType(state, args[0], COSMO_USER_FILE)) {
|
||||||
|
cosmoV_typeError(state, "file:__gc()", "<file>", "%s",
|
||||||
|
cosmoV_typeStr(args[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
CObjObject *fileObj = cosmoV_readObject(args[0]);
|
||||||
|
FILE *file = cosmoO_getUserP(fileObj);
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CObjObject *pushFileObj(CState *state, FILE *file)
|
||||||
|
{
|
||||||
|
CObjObject *fileObj = cosmoO_newObject(state);
|
||||||
|
cosmoV_pushRef(state, (CObj *)fileObj);
|
||||||
|
cosmoO_setUserP(fileObj, file);
|
||||||
|
cosmoO_setUserT(fileObj, COSMO_USER_FILE);
|
||||||
|
|
||||||
|
// grab and set proto
|
||||||
|
cosmoV_pushRef(state, (CObj *)fileObj);
|
||||||
|
cosmoV_pushString(state, "file");
|
||||||
|
cosmoV_getRegistry(state);
|
||||||
|
cosmoV_setProto(state);
|
||||||
|
|
||||||
|
cosmoO_lock(fileObj);
|
||||||
|
return fileObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cosmoB_osOpen(CState *state, int nargs, CValue *args)
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
|
||||||
|
if (nargs != 1) {
|
||||||
|
cosmoV_error(state, "os.open() expected 1 argument, got %d!", nargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_STRING(args[0])) {
|
if (!IS_STRING(args[0])) {
|
||||||
cosmoV_typeError(state, "os.read()", "<string>", "%s", cosmoV_typeStr(args[0]));
|
cosmoV_typeError(state, "os.open()", "<string>", "%s", cosmoV_typeStr(args[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
CObjString *str = cosmoV_readString(args[0]);
|
const char *filePath = cosmoV_readCString(args[0]);
|
||||||
|
file = fopen(filePath, "rb");
|
||||||
// open file
|
|
||||||
FILE *file = fopen(str->str, "rb");
|
|
||||||
char *buf;
|
|
||||||
size_t size, bRead;
|
|
||||||
|
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
// return nil, file doesn't exist
|
cosmoV_pushBoolean(state, true);
|
||||||
return 0;
|
cosmoV_pushFString(state, "Failed to open %s!", filePath);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// grab the size of the file
|
cosmoV_pushBoolean(state, false);
|
||||||
fseek(file, 0L, SEEK_END);
|
pushFileObj(state, file);
|
||||||
size = ftell(file);
|
return 2;
|
||||||
rewind(file);
|
|
||||||
|
|
||||||
buf = cosmoM_xmalloc(state, size + 1); // +1 for the NULL terminator
|
|
||||||
bRead = fread(buf, sizeof(char), size, file); // read the file into the buffer
|
|
||||||
|
|
||||||
if (bRead < size) {
|
|
||||||
// an error occured! we don't need to really throw an error, returning a nil is good enough
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[bRead] = '\0'; // place the NULL terminator at the end of the buffer
|
|
||||||
|
|
||||||
// push the string to the stack to return
|
|
||||||
cosmoV_pushValue(state, cosmoV_newRef(cosmoO_takeString(state, buf, bRead)));
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// os.time()
|
// os.time()
|
||||||
@ -309,9 +386,8 @@ int cosmoB_osSystem(CState *state, int nargs, CValue *args)
|
|||||||
|
|
||||||
COSMO_API void cosmoB_loadOS(CState *state)
|
COSMO_API void cosmoB_loadOS(CState *state)
|
||||||
{
|
{
|
||||||
const char *identifiers[] = {"read", "time", "system"};
|
const char *identifiers[] = {"open", "time", "system"};
|
||||||
|
CosmoCFunction osLib[] = {cosmoB_osOpen, cosmoB_osTime, cosmoB_osSystem};
|
||||||
CosmoCFunction osLib[] = {cosmoB_osRead, cosmoB_osTime, cosmoB_osSystem};
|
|
||||||
|
|
||||||
cosmoV_pushString(state, "os");
|
cosmoV_pushString(state, "os");
|
||||||
|
|
||||||
@ -322,7 +398,25 @@ COSMO_API void cosmoB_loadOS(CState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cosmoV_makeObject(state, i);
|
cosmoV_makeObject(state, i);
|
||||||
cosmoV_register(state, 1); // register the os.* object to the global table
|
cosmoV_addGlobals(state, 1); // register the os.* object to the global table
|
||||||
|
|
||||||
|
// make file proto
|
||||||
|
cosmoV_pushString(state, "file");
|
||||||
|
|
||||||
|
CObjObject *fileProto = cosmoO_newObject(state);
|
||||||
|
cosmoV_pushRef(state, (CObj *)fileProto);
|
||||||
|
|
||||||
|
cosmoV_pushRef(state, (CObj *)fileProto);
|
||||||
|
cosmoV_pushString(state, "read");
|
||||||
|
cosmoV_pushCFunction(state, fileB_read);
|
||||||
|
cosmoV_set(state);
|
||||||
|
|
||||||
|
cosmoV_pushRef(state, (CObj *)fileProto);
|
||||||
|
cosmoV_pushString(state, "__gc");
|
||||||
|
cosmoV_pushCFunction(state, fileB_gc);
|
||||||
|
cosmoV_set(state);
|
||||||
|
|
||||||
|
cosmoV_addRegistry(state, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================================================================ [STRING.*]
|
// ================================================================ [STRING.*]
|
||||||
@ -578,7 +672,7 @@ void cosmoB_loadStrLib(CState *state)
|
|||||||
cosmoV_registerProtoObject(state, COBJ_STRING, obj);
|
cosmoV_registerProtoObject(state, COBJ_STRING, obj);
|
||||||
|
|
||||||
// register "string" to the global table
|
// register "string" to the global table
|
||||||
cosmoV_register(state, 1);
|
cosmoV_addGlobals(state, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================================================================ [MATH]
|
// ================================================================ [MATH]
|
||||||
@ -773,7 +867,7 @@ void cosmoB_loadMathLib(CState *state)
|
|||||||
|
|
||||||
// make the object and register it as a global to the state
|
// make the object and register it as a global to the state
|
||||||
cosmoV_makeObject(state, i);
|
cosmoV_makeObject(state, i);
|
||||||
cosmoV_register(state, 1);
|
cosmoV_addGlobals(state, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================================================================ [VM.*]
|
// ================================================================ [VM.*]
|
||||||
@ -924,5 +1018,5 @@ void cosmoB_loadVM(CState *state)
|
|||||||
cosmoV_makeObject(state, 5); // makes the vm object
|
cosmoV_makeObject(state, 5); // makes the vm object
|
||||||
|
|
||||||
// register "vm" to the global table
|
// register "vm" to the global table
|
||||||
cosmoV_register(state, 1);
|
cosmoV_addGlobals(state, 1);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,13 @@
|
|||||||
|
|
||||||
#include "cstate.h"
|
#include "cstate.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
COSMO_USER_NONE, // CObjObject is not a userdata object
|
||||||
|
COSMO_USER_FILE, // CObjObject is a file object (see cosmoB_osOpen)
|
||||||
|
COSMO_USER_START // the first user type for user-defined userdata
|
||||||
|
};
|
||||||
|
|
||||||
/* loads all of the base library, including:
|
/* loads all of the base library, including:
|
||||||
- base library ("print", "assert", "type", "pcall", "loadstring", etc.)
|
- base library ("print", "assert", "type", "pcall", "loadstring", etc.)
|
||||||
- object library
|
- object library
|
||||||
|
68
src/cmem.c
68
src/cmem.c
@ -6,6 +6,7 @@
|
|||||||
#include "cstate.h"
|
#include "cstate.h"
|
||||||
#include "ctable.h"
|
#include "ctable.h"
|
||||||
#include "cvalue.h"
|
#include "cvalue.h"
|
||||||
|
#include "cvm.h"
|
||||||
|
|
||||||
// realloc wrapper
|
// realloc wrapper
|
||||||
void *cosmoM_reallocate(CState *state, void *buf, size_t oldSize, size_t newSize)
|
void *cosmoM_reallocate(CState *state, void *buf, size_t oldSize, size_t newSize)
|
||||||
@ -246,22 +247,23 @@ static void sweep(CState *state)
|
|||||||
prev->next = object;
|
prev->next = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// call __gc on the object
|
||||||
|
CObjObject *protoObject = cosmoO_grabProto(oldObj);
|
||||||
|
CValue res;
|
||||||
|
|
||||||
|
// use user-defined __gc
|
||||||
|
if (protoObject != NULL && cosmoO_getIString(state, protoObject, ISTRING_GC, &res)) {
|
||||||
|
cosmoV_pushValue(state, res);
|
||||||
|
cosmoV_pushRef(state, (CObj *)oldObj);
|
||||||
|
cosmoV_call(state, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
cosmoO_free(state, oldObj);
|
cosmoO_free(state, oldObj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void markUserRoots(CState *state)
|
|
||||||
{
|
|
||||||
CObj *root = state->userRoots;
|
|
||||||
|
|
||||||
// traverse userRoots and mark all the object
|
|
||||||
while (root != NULL) {
|
|
||||||
markObject(state, root);
|
|
||||||
root = root->nextRoot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void markRoots(CState *state)
|
static void markRoots(CState *state)
|
||||||
{
|
{
|
||||||
// mark all values on the stack
|
// mark all values on the stack
|
||||||
@ -285,8 +287,7 @@ static void markRoots(CState *state)
|
|||||||
for (int i = 0; i < ISTRING_MAX; i++)
|
for (int i = 0; i < ISTRING_MAX; i++)
|
||||||
markObject(state, (CObj *)state->iStrings[i]);
|
markObject(state, (CObj *)state->iStrings[i]);
|
||||||
|
|
||||||
// mark the user defined roots
|
markTable(state, &state->registry);
|
||||||
markUserRoots(state);
|
|
||||||
|
|
||||||
for (int i = 0; i < COBJ_MAX; i++)
|
for (int i = 0; i < COBJ_MAX; i++)
|
||||||
markObject(state, (CObj *)state->protoObjects[i]);
|
markObject(state, (CObj *)state->protoObjects[i]);
|
||||||
@ -323,44 +324,3 @@ COSMO_API void cosmoM_updateThreshhold(CState *state)
|
|||||||
{
|
{
|
||||||
state->nextGC = state->allocatedBytes * HEAP_GROW_FACTOR;
|
state->nextGC = state->allocatedBytes * HEAP_GROW_FACTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
COSMO_API void cosmoM_addRoot(CState *state, CObj *newRoot)
|
|
||||||
{
|
|
||||||
// first, check and make sure this root doesn't already exist in the list
|
|
||||||
CObj *root = state->userRoots;
|
|
||||||
while (root != NULL) {
|
|
||||||
if (root == newRoot) // found in the list, abort
|
|
||||||
return;
|
|
||||||
|
|
||||||
root = root->nextRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
// adds root to userRoot linked list
|
|
||||||
newRoot->nextRoot = state->userRoots;
|
|
||||||
state->userRoots = newRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
COSMO_API void cosmoM_removeRoot(CState *state, CObj *oldRoot)
|
|
||||||
{
|
|
||||||
CObj *prev = NULL;
|
|
||||||
CObj *root = state->userRoots;
|
|
||||||
|
|
||||||
// traverse the userRoot linked list
|
|
||||||
while (root != NULL) {
|
|
||||||
if (root == oldRoot) { // found root in list
|
|
||||||
|
|
||||||
// remove from the linked list
|
|
||||||
if (prev == NULL) {
|
|
||||||
state->userRoots = root->nextRoot;
|
|
||||||
} else {
|
|
||||||
prev->nextRoot = root->nextRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
root->nextRoot = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
prev = root;
|
|
||||||
root = root->nextRoot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -67,13 +67,6 @@ COSMO_API bool cosmoM_checkGarbage(CState *state,
|
|||||||
COSMO_API void cosmoM_collectGarbage(CState *state);
|
COSMO_API void cosmoM_collectGarbage(CState *state);
|
||||||
COSMO_API void cosmoM_updateThreshhold(CState *state);
|
COSMO_API void cosmoM_updateThreshhold(CState *state);
|
||||||
|
|
||||||
// lets the VM know you are holding a reference to a CObj and to not free it
|
|
||||||
// NOTE: prefer to use the stack when possible
|
|
||||||
COSMO_API void cosmoM_addRoot(CState *state, CObj *newRoot);
|
|
||||||
|
|
||||||
// lets the VM know this root is no longer held in a reference and is able to be freed
|
|
||||||
COSMO_API void cosmoM_removeRoot(CState *state, CObj *oldRoot);
|
|
||||||
|
|
||||||
// wrapper for cosmoM_reallocate so we can track our memory usage
|
// wrapper for cosmoM_reallocate so we can track our memory usage
|
||||||
static inline void *cosmoM_xmalloc(CState *state, size_t sz)
|
static inline void *cosmoM_xmalloc(CState *state, size_t sz)
|
||||||
{
|
{
|
||||||
|
@ -31,7 +31,6 @@ CObj *cosmoO_allocateBase(CState *state, size_t sz, CObjType type)
|
|||||||
obj->next = state->objects;
|
obj->next = state->objects;
|
||||||
state->objects = obj;
|
state->objects = obj;
|
||||||
|
|
||||||
obj->nextRoot = NULL;
|
|
||||||
#ifdef GC_DEBUG
|
#ifdef GC_DEBUG
|
||||||
printf("allocated %s %p\n", cosmoO_typeStr(obj), obj);
|
printf("allocated %s %p\n", cosmoO_typeStr(obj), obj);
|
||||||
#endif
|
#endif
|
||||||
@ -51,9 +50,9 @@ void cosmoO_free(CState *state, CObj *obj)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case COBJ_OBJECT: {
|
case COBJ_OBJECT: {
|
||||||
CObjObject *objTbl = (CObjObject *)obj;
|
CObjObject *objObj = (CObjObject *)obj;
|
||||||
cosmoT_clearTable(state, &objTbl->tbl);
|
cosmoT_clearTable(state, &objObj->tbl);
|
||||||
cosmoM_free(state, CObjObject, objTbl);
|
cosmoM_free(state, CObjObject, objObj);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case COBJ_TABLE: {
|
case COBJ_TABLE: {
|
||||||
@ -492,6 +491,7 @@ void cosmoO_unlock(CObjObject *object)
|
|||||||
object->isLocked = false;
|
object->isLocked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool rawgetIString(CState *state, CObjObject *object, int flag, CValue *val)
|
bool rawgetIString(CState *state, CObjObject *object, int flag, CValue *val)
|
||||||
{
|
{
|
||||||
if (readFlag(object->istringFlags, flag))
|
if (readFlag(object->istringFlags, flag))
|
||||||
|
@ -34,7 +34,6 @@ typedef int (*CosmoCFunction)(CState *state, int argCount, CValue *args);
|
|||||||
struct CObj
|
struct CObj
|
||||||
{
|
{
|
||||||
struct CObj *next;
|
struct CObj *next;
|
||||||
struct CObj *nextRoot; // for the root linked list
|
|
||||||
struct CObjObject *proto; // protoobject, describes the behavior of the object
|
struct CObjObject *proto; // protoobject, describes the behavior of the object
|
||||||
CObjType type;
|
CObjType type;
|
||||||
bool isMarked; // for the GC
|
bool isMarked; // for the GC
|
||||||
|
50
src/cstate.c
50
src/cstate.c
@ -12,6 +12,7 @@ CPanic *cosmoV_newPanic(CState *state)
|
|||||||
CPanic *panic = cosmoM_xmalloc(state, sizeof(CPanic));
|
CPanic *panic = cosmoM_xmalloc(state, sizeof(CPanic));
|
||||||
panic->top = state->top;
|
panic->top = state->top;
|
||||||
panic->frameCount = state->frameCount;
|
panic->frameCount = state->frameCount;
|
||||||
|
panic->freezeGC = state->freezeGC;
|
||||||
panic->prev = state->panic;
|
panic->prev = state->panic;
|
||||||
state->panic = panic;
|
state->panic = panic;
|
||||||
|
|
||||||
@ -41,7 +42,6 @@ CState *cosmoV_newState()
|
|||||||
|
|
||||||
// GC
|
// GC
|
||||||
state->objects = NULL;
|
state->objects = NULL;
|
||||||
state->userRoots = NULL;
|
|
||||||
state->grayStack.count = 0;
|
state->grayStack.count = 0;
|
||||||
state->grayStack.capacity = 2;
|
state->grayStack.capacity = 2;
|
||||||
state->grayStack.array = NULL;
|
state->grayStack.array = NULL;
|
||||||
@ -61,11 +61,13 @@ CState *cosmoV_newState()
|
|||||||
state->iStrings[i] = NULL;
|
state->iStrings[i] = NULL;
|
||||||
|
|
||||||
cosmoT_initTable(state, &state->strings, 16); // init string table
|
cosmoT_initTable(state, &state->strings, 16); // init string table
|
||||||
|
cosmoT_initTable(state, &state->registry, 16);
|
||||||
|
|
||||||
state->globals = cosmoO_newTable(state); // init global table
|
state->globals = cosmoO_newTable(state); // init global table
|
||||||
|
|
||||||
// setup all strings used by the VM
|
// setup all strings used by the VM
|
||||||
state->iStrings[ISTRING_INIT] = cosmoO_copyString(state, "__init", 6);
|
state->iStrings[ISTRING_INIT] = cosmoO_copyString(state, "__init", 6);
|
||||||
|
state->iStrings[ISTRING_GC] = cosmoO_copyString(state, "__gc", 4);
|
||||||
state->iStrings[ISTRING_TOSTRING] = cosmoO_copyString(state, "__tostring", 10);
|
state->iStrings[ISTRING_TOSTRING] = cosmoO_copyString(state, "__tostring", 10);
|
||||||
state->iStrings[ISTRING_TONUMBER] = cosmoO_copyString(state, "__tonumber", 10);
|
state->iStrings[ISTRING_TONUMBER] = cosmoO_copyString(state, "__tonumber", 10);
|
||||||
state->iStrings[ISTRING_INDEX] = cosmoO_copyString(state, "__index", 7);
|
state->iStrings[ISTRING_INDEX] = cosmoO_copyString(state, "__index", 7);
|
||||||
@ -119,6 +121,8 @@ void cosmoV_freeState(CState *state)
|
|||||||
// free our string table (the string table includes the internal VM strings)
|
// free our string table (the string table includes the internal VM strings)
|
||||||
cosmoT_clearTable(state, &state->strings);
|
cosmoT_clearTable(state, &state->strings);
|
||||||
|
|
||||||
|
cosmoT_clearTable(state, &state->registry);
|
||||||
|
|
||||||
// free our gray stack & finally free the state structure
|
// free our gray stack & finally free the state structure
|
||||||
cosmoM_freeArray(state, CObj *, state->grayStack.array, state->grayStack.capacity);
|
cosmoM_freeArray(state, CObj *, state->grayStack.array, state->grayStack.capacity);
|
||||||
|
|
||||||
@ -132,7 +136,7 @@ void cosmoV_freeState(CState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// expects 2*pairs values on the stack, each pair should consist of 1 key and 1 value
|
// expects 2*pairs values on the stack, each pair should consist of 1 key and 1 value
|
||||||
void cosmoV_register(CState *state, int pairs)
|
void cosmoV_addGlobals(CState *state, int pairs)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < pairs; i++) {
|
for (int i = 0; i < pairs; i++) {
|
||||||
StkPtr key = cosmoV_getTop(state, 1);
|
StkPtr key = cosmoV_getTop(state, 1);
|
||||||
@ -145,6 +149,48 @@ void cosmoV_register(CState *state, int pairs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// expects 2*pairs values on the stack, each pair should consist of 1 key and 1 value
|
||||||
|
void cosmoV_addRegistry(CState *state, int pairs)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < pairs; i++) {
|
||||||
|
StkPtr key = cosmoV_getTop(state, 1);
|
||||||
|
StkPtr val = cosmoV_getTop(state, 0);
|
||||||
|
|
||||||
|
CValue *oldVal = cosmoT_insert(state, &state->registry, *key);
|
||||||
|
*oldVal = *val;
|
||||||
|
|
||||||
|
cosmoV_setTop(state, 2); // pops the 2 values off the stack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// expects 1 key on the stack, pushes result
|
||||||
|
void cosmoV_getRegistry(CState *state) {
|
||||||
|
CValue key = *cosmoV_pop(state);
|
||||||
|
CValue val;
|
||||||
|
|
||||||
|
if (!cosmoT_get(state, &state->registry, key, &val)) {
|
||||||
|
cosmoV_error(state, "failed to grab %s from registry", cosmoV_typeStr(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
cosmoV_pushValue(state, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cosmoV_setProto(CState *state) {
|
||||||
|
StkPtr objVal = cosmoV_getTop(state, 1);
|
||||||
|
StkPtr protoVal = cosmoV_getTop(state, 0);
|
||||||
|
|
||||||
|
if (!IS_REF(*objVal) || !IS_OBJECT(*protoVal)) {
|
||||||
|
cosmoV_error(state, "cannot set %s to proto of type %s", cosmoV_typeStr(*objVal), cosmoV_typeStr(*protoVal));
|
||||||
|
}
|
||||||
|
|
||||||
|
// actually set the protos
|
||||||
|
CObj *obj = cosmoV_readRef(*objVal);
|
||||||
|
CObjObject *proto = cosmoV_readObject(*protoVal);
|
||||||
|
obj->proto = proto;
|
||||||
|
|
||||||
|
cosmoV_setTop(state, 2);
|
||||||
|
}
|
||||||
|
|
||||||
void cosmoV_printStack(CState *state)
|
void cosmoV_printStack(CState *state)
|
||||||
{
|
{
|
||||||
printf("==== [[ stack dump ]] ====\n");
|
printf("==== [[ stack dump ]] ====\n");
|
||||||
|
20
src/cstate.h
20
src/cstate.h
@ -18,6 +18,7 @@ struct CCallFrame
|
|||||||
typedef enum IStringEnum
|
typedef enum IStringEnum
|
||||||
{
|
{
|
||||||
ISTRING_INIT, // __init
|
ISTRING_INIT, // __init
|
||||||
|
ISTRING_GC, // __gc
|
||||||
ISTRING_TOSTRING, // __tostring
|
ISTRING_TOSTRING, // __tostring
|
||||||
ISTRING_TONUMBER, // __tonumber
|
ISTRING_TONUMBER, // __tonumber
|
||||||
ISTRING_EQUAL, // __equals
|
ISTRING_EQUAL, // __equals
|
||||||
@ -46,6 +47,7 @@ typedef struct CPanic
|
|||||||
StkPtr top;
|
StkPtr top;
|
||||||
struct CPanic *prev;
|
struct CPanic *prev;
|
||||||
int frameCount;
|
int frameCount;
|
||||||
|
int freezeGC;
|
||||||
} CPanic;
|
} CPanic;
|
||||||
|
|
||||||
struct CState
|
struct CState
|
||||||
@ -55,6 +57,7 @@ struct CState
|
|||||||
CObjObject *protoObjects[COBJ_MAX]; // proto object for each COBJ type [NULL = no default proto]
|
CObjObject *protoObjects[COBJ_MAX]; // proto object for each COBJ type [NULL = no default proto]
|
||||||
CObjString *iStrings[ISTRING_MAX]; // strings used internally by the VM, eg. __init, __index
|
CObjString *iStrings[ISTRING_MAX]; // strings used internally by the VM, eg. __init, __index
|
||||||
CTable strings;
|
CTable strings;
|
||||||
|
CTable registry;
|
||||||
ArrayCObj grayStack; // keeps track of which objects *haven't yet* been traversed in our GC, but
|
ArrayCObj grayStack; // keeps track of which objects *haven't yet* been traversed in our GC, but
|
||||||
// *have been* found
|
// *have been* found
|
||||||
|
|
||||||
@ -62,14 +65,12 @@ struct CState
|
|||||||
CObjTable *globals;
|
CObjTable *globals;
|
||||||
CValue *top; // top of the stack
|
CValue *top; // top of the stack
|
||||||
CObj *objects; // tracks all of our allocated objects
|
CObj *objects; // tracks all of our allocated objects
|
||||||
CObj *userRoots; // user definable roots, this holds CObjs that should be considered "roots",
|
|
||||||
// lets the VM know you are holding a reference to a CObj in your code
|
|
||||||
CPanic *panic;
|
CPanic *panic;
|
||||||
|
|
||||||
int freezeGC; // when > 0, GC events will be ignored (for internal use)
|
|
||||||
int frameCount;
|
|
||||||
size_t allocatedBytes;
|
size_t allocatedBytes;
|
||||||
size_t nextGC; // when allocatedBytes reaches this threshhold, trigger a GC event
|
size_t nextGC; // when allocatedBytes reaches this threshhold, trigger a GC event
|
||||||
|
int freezeGC; // when > 0, GC events will be ignored (for internal use)
|
||||||
|
int frameCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
CPanic *cosmoV_newPanic(CState *state);
|
CPanic *cosmoV_newPanic(CState *state);
|
||||||
@ -79,7 +80,16 @@ COSMO_API CState *cosmoV_newState();
|
|||||||
COSMO_API void cosmoV_freeState(CState *state);
|
COSMO_API void cosmoV_freeState(CState *state);
|
||||||
|
|
||||||
// expects 2*pairs values on the stack, each pair should consist of 1 key and 1 value
|
// expects 2*pairs values on the stack, each pair should consist of 1 key and 1 value
|
||||||
COSMO_API void cosmoV_register(CState *state, int pairs);
|
COSMO_API void cosmoV_addGlobals(CState *state, int pairs);
|
||||||
|
|
||||||
|
// expects 2*pairs values on the stack, each pair should consist of 1 key and 1 value
|
||||||
|
COSMO_API void cosmoV_addRegistry(CState *state, int pairs);
|
||||||
|
|
||||||
|
// expects 1 key on the stack, pushes result
|
||||||
|
COSMO_API void cosmoV_getRegistry(CState *state);
|
||||||
|
|
||||||
|
// expects <object>->proto = <object> (2 total) to be on the stack
|
||||||
|
COSMO_API void cosmoV_setProto(CState *state);
|
||||||
|
|
||||||
COSMO_API void cosmoV_printStack(CState *state);
|
COSMO_API void cosmoV_printStack(CState *state);
|
||||||
|
|
||||||
|
45
src/cvm.c
45
src/cvm.c
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
#define cosmoV_protect(panic) setjmp(panic->jmp) == 0
|
#define cosmoV_protect(panic) setjmp(panic->jmp) == 0
|
||||||
|
|
||||||
COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...)
|
void cosmoV_pushFString(CState *state, const char *format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
@ -21,7 +21,7 @@ COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// inserts val at state->top - indx - 1, moving everything else up
|
// inserts val at state->top - indx - 1, moving everything else up
|
||||||
COSMO_API void cosmo_insert(CState *state, int indx, CValue val)
|
void cosmoV_insert(CState *state, int indx, CValue val)
|
||||||
{
|
{
|
||||||
StkPtr tmp = cosmoV_getTop(state, indx);
|
StkPtr tmp = cosmoV_getTop(state, indx);
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ COSMO_API void cosmo_insert(CState *state, int indx, CValue val)
|
|||||||
state->top++;
|
state->top++;
|
||||||
}
|
}
|
||||||
|
|
||||||
COSMO_API bool cosmoV_undump(CState *state, cosmo_Reader reader, const void *ud)
|
bool cosmoV_undump(CState *state, cosmo_Reader reader, const void *ud)
|
||||||
{
|
{
|
||||||
CObjFunction *func;
|
CObjFunction *func;
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ COSMO_API bool cosmoV_undump(CState *state, cosmo_Reader reader, const void *ud)
|
|||||||
|
|
||||||
// returns false if failed, error will be on the top of the stack. true if successful, closure will
|
// returns false if failed, error will be on the top of the stack. true if successful, closure will
|
||||||
// be on the top of the stack
|
// be on the top of the stack
|
||||||
COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *name)
|
bool cosmoV_compileString(CState *state, const char *src, const char *name)
|
||||||
{
|
{
|
||||||
CObjFunction *func;
|
CObjFunction *func;
|
||||||
CPanic *panic = cosmoV_newPanic(state);
|
CPanic *panic = cosmoV_newPanic(state);
|
||||||
@ -77,7 +77,7 @@ COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
COSMO_API void cosmoV_printError(CState *state, CObjError *err)
|
void cosmoV_printError(CState *state, CObjError *err)
|
||||||
{
|
{
|
||||||
// print stack trace
|
// print stack trace
|
||||||
for (int i = 0; i < err->frameCount; i++) {
|
for (int i = 0; i < err->frameCount; i++) {
|
||||||
@ -122,6 +122,7 @@ void cosmoV_throw(CState *state)
|
|||||||
if (state->panic) {
|
if (state->panic) {
|
||||||
state->top = state->panic->top;
|
state->top = state->panic->top;
|
||||||
state->frameCount = state->panic->frameCount;
|
state->frameCount = state->panic->frameCount;
|
||||||
|
state->freezeGC = state->panic->freezeGC;
|
||||||
cosmoV_pushValue(state, val);
|
cosmoV_pushValue(state, val);
|
||||||
longjmp(state->panic->jmp, 1);
|
longjmp(state->panic->jmp, 1);
|
||||||
} else {
|
} else {
|
||||||
@ -438,7 +439,7 @@ static inline bool isFalsey(StkPtr val)
|
|||||||
return IS_NIL(*val) || (IS_BOOLEAN(*val) && !cosmoV_readBoolean(*val));
|
return IS_NIL(*val) || (IS_BOOLEAN(*val) && !cosmoV_readBoolean(*val));
|
||||||
}
|
}
|
||||||
|
|
||||||
COSMO_API CObjObject *cosmoV_makeObject(CState *state, int pairs)
|
CObjObject *cosmoV_makeObject(CState *state, int pairs)
|
||||||
{
|
{
|
||||||
StkPtr key, val;
|
StkPtr key, val;
|
||||||
CObjObject *newObj = cosmoO_newObject(state);
|
CObjObject *newObj = cosmoO_newObject(state);
|
||||||
@ -459,7 +460,7 @@ COSMO_API CObjObject *cosmoV_makeObject(CState *state, int pairs)
|
|||||||
return newObj;
|
return newObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
COSMO_API bool cosmoV_registerProtoObject(CState *state, CObjType objType, CObjObject *obj)
|
bool cosmoV_registerProtoObject(CState *state, CObjType objType, CObjObject *obj)
|
||||||
{
|
{
|
||||||
bool replaced = state->protoObjects[objType] != NULL;
|
bool replaced = state->protoObjects[objType] != NULL;
|
||||||
state->protoObjects[objType] = obj;
|
state->protoObjects[objType] = obj;
|
||||||
@ -468,7 +469,7 @@ COSMO_API bool cosmoV_registerProtoObject(CState *state, CObjType objType, CObjO
|
|||||||
CObj *curr = state->objects;
|
CObj *curr = state->objects;
|
||||||
while (curr != NULL) {
|
while (curr != NULL) {
|
||||||
// update the proto
|
// update the proto
|
||||||
if (curr->type == objType && curr->proto != NULL) {
|
if (curr != (CObj *)obj && curr->type == objType && curr->proto != NULL) {
|
||||||
curr->proto = obj;
|
curr->proto = obj;
|
||||||
}
|
}
|
||||||
curr = curr->next;
|
curr = curr->next;
|
||||||
@ -477,7 +478,7 @@ COSMO_API bool cosmoV_registerProtoObject(CState *state, CObjType objType, CObjO
|
|||||||
return replaced;
|
return replaced;
|
||||||
}
|
}
|
||||||
|
|
||||||
COSMO_API void cosmoV_makeTable(CState *state, int pairs)
|
void cosmoV_makeTable(CState *state, int pairs)
|
||||||
{
|
{
|
||||||
StkPtr key, val;
|
StkPtr key, val;
|
||||||
CObjTable *newObj = cosmoO_newTable(state);
|
CObjTable *newObj = cosmoO_newTable(state);
|
||||||
@ -529,7 +530,7 @@ void cosmoV_rawset(CState *state, CObj *_obj, CValue key, CValue val)
|
|||||||
cosmoO_setRawObject(state, object, key, val, _obj);
|
cosmoO_setRawObject(state, object, key, val, _obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
COSMO_API void cosmoV_get(CState *state)
|
void cosmoV_get(CState *state)
|
||||||
{
|
{
|
||||||
CValue val;
|
CValue val;
|
||||||
StkPtr obj = cosmoV_getTop(state, 1); // object was pushed first
|
StkPtr obj = cosmoV_getTop(state, 1); // object was pushed first
|
||||||
@ -547,7 +548,7 @@ COSMO_API void cosmoV_get(CState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// yes, this would technically make it possible to set fields of types other than <string>. go crazy
|
// yes, this would technically make it possible to set fields of types other than <string>. go crazy
|
||||||
COSMO_API void cosmoV_set(CState *state)
|
void cosmoV_set(CState *state)
|
||||||
{
|
{
|
||||||
StkPtr obj = cosmoV_getTop(state, 2); // object was pushed first
|
StkPtr obj = cosmoV_getTop(state, 2); // object was pushed first
|
||||||
StkPtr key = cosmoV_getTop(state, 1); // then the key
|
StkPtr key = cosmoV_getTop(state, 1); // then the key
|
||||||
@ -563,7 +564,7 @@ COSMO_API void cosmoV_set(CState *state)
|
|||||||
cosmoV_setTop(state, 3);
|
cosmoV_setTop(state, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
COSMO_API void cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val)
|
void cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val)
|
||||||
{
|
{
|
||||||
cosmoV_rawget(state, obj, key, val);
|
cosmoV_rawget(state, obj, key, val);
|
||||||
|
|
||||||
@ -577,6 +578,19 @@ COSMO_API void cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *va
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cosmoV_isValueUserType(CState *state, CValue val, int userType) {
|
||||||
|
if (!IS_OBJECT(val)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CObjObject *obj = cosmoV_readObject(val);
|
||||||
|
if (obj->userT != userType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int _tbl__next(CState *state, int nargs, CValue *args)
|
int _tbl__next(CState *state, int nargs, CValue *args)
|
||||||
{
|
{
|
||||||
if (nargs != 1) {
|
if (nargs != 1) {
|
||||||
@ -835,7 +849,8 @@ int cosmoV_execute(CState *state)
|
|||||||
|
|
||||||
CObj *obj = cosmoV_readRef(*temp);
|
CObj *obj = cosmoV_readRef(*temp);
|
||||||
CObjObject *proto = cosmoO_grabProto(obj);
|
CObjObject *proto = cosmoO_grabProto(obj);
|
||||||
CValue val; // to hold our value
|
CValue val = cosmoV_newNil(); // to hold our value
|
||||||
|
|
||||||
|
|
||||||
if (proto != NULL) {
|
if (proto != NULL) {
|
||||||
// check for __index metamethod
|
// check for __index metamethod
|
||||||
@ -906,7 +921,7 @@ int cosmoV_execute(CState *state)
|
|||||||
}
|
}
|
||||||
CASE(OP_GETOBJECT) :
|
CASE(OP_GETOBJECT) :
|
||||||
{
|
{
|
||||||
CValue val; // to hold our value
|
CValue val = cosmoV_newNil(); // to hold our value
|
||||||
StkPtr temp = cosmoV_getTop(state, 0); // that should be the object
|
StkPtr temp = cosmoV_getTop(state, 0); // that should be the object
|
||||||
uint16_t ident = READUINT(frame); // use for the key
|
uint16_t ident = READUINT(frame); // use for the key
|
||||||
|
|
||||||
@ -924,7 +939,7 @@ int cosmoV_execute(CState *state)
|
|||||||
}
|
}
|
||||||
CASE(OP_GETMETHOD) :
|
CASE(OP_GETMETHOD) :
|
||||||
{
|
{
|
||||||
CValue val; // to hold our value
|
CValue val = cosmoV_newNil(); // to hold our value
|
||||||
StkPtr temp = cosmoV_getTop(state, 0); // that should be the object
|
StkPtr temp = cosmoV_getTop(state, 0); // that should be the object
|
||||||
uint16_t ident = READUINT(frame); // use for the key
|
uint16_t ident = READUINT(frame); // use for the key
|
||||||
|
|
||||||
|
@ -36,11 +36,11 @@ COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...);
|
|||||||
COSMO_API void cosmoV_printError(CState *state, CObjError *err);
|
COSMO_API void cosmoV_printError(CState *state, CObjError *err);
|
||||||
COSMO_API void cosmoV_throw(CState *state);
|
COSMO_API void cosmoV_throw(CState *state);
|
||||||
COSMO_API void cosmoV_error(CState *state, const char *format, ...);
|
COSMO_API void cosmoV_error(CState *state, const char *format, ...);
|
||||||
COSMO_API void cosmo_insert(CState *state, int indx, CValue val);
|
COSMO_API void cosmoV_insert(CState *state, int indx, CValue val);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Sets the default proto objects for the passed objType. Also walks through the object heap and
|
Sets the default proto objects for the passed objType. Also walks through the object heap and
|
||||||
updates protos for the passed objType if that CObj* has no proto.
|
updates protos for the passed objType if that CObj* has no proto.
|
||||||
|
|
||||||
returns true if replacing a previously registered proto object for this type
|
returns true if replacing a previously registered proto object for this type
|
||||||
*/
|
*/
|
||||||
@ -72,13 +72,16 @@ COSMO_API bool cosmoV_undump(CState *state, cosmo_Reader reader, const void *ud)
|
|||||||
COSMO_API void cosmoV_get(CState *state);
|
COSMO_API void cosmoV_get(CState *state);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
expects object to be pushed, then the key, and finally the new value. pops the key & object
|
expects object to be pushed, then the key, and finally the new value. pops the object, key & value
|
||||||
*/
|
*/
|
||||||
COSMO_API void cosmoV_set(CState *state);
|
COSMO_API void cosmoV_set(CState *state);
|
||||||
|
|
||||||
// wraps the closure into a CObjMethod, so the function is called as an invoked method
|
// wraps the closure into a CObjMethod, so the function is called as an invoked method
|
||||||
COSMO_API void cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val);
|
COSMO_API void cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val);
|
||||||
|
|
||||||
|
// check if the value at the top of the stack is a <obj> user type
|
||||||
|
COSMO_API bool cosmoV_isValueUserType(CState *state, CValue val, int userType);
|
||||||
|
|
||||||
// nice to have wrappers
|
// nice to have wrappers
|
||||||
|
|
||||||
// pushes a raw CValue to the stack, might throw an error if the stack is overflowed (with the
|
// pushes a raw CValue to the stack, might throw an error if the stack is overflowed (with the
|
||||||
|
Loading…
Reference in New Issue
Block a user