Compare commits

...

18 Commits

Author SHA1 Message Date
CPunch 5169aca6d0 forgot to update this a while back 2023-05-28 21:16:30 -05:00
CPunch c34c5850e2 whoops, need to update the command to run the testsuite 2023-05-28 21:13:51 -05:00
CPunch 07ba4c731e update README.md 2023-05-28 21:11:52 -05:00
cpunk 788911130d
Merge pull request #6 from CPunch/chunk-loading
Chunk loading
2023-05-28 20:59:10 -05:00
CPunch c464a76849 minor usage fix 2023-05-28 20:57:53 -05:00
CPunch 8c6ba18848 major main.c refactoring
- now takes command line arguments:
Usage: ./bin/cosmo [-clsr] [args]

available options are:
-c <in> <out>   compile <in> and dump to <out>
-l <in>         load dump from <in>
-s <in...>              compile and run <in...> script(s)
-r                      start the repl
2023-05-28 20:52:12 -05:00
CPunch 93a09698a9 minor stack fixes 2023-05-28 12:19:52 -05:00
CPunch be49ec5af5 proper error handling for dump edgecases 2023-05-28 12:16:00 -05:00
CPunch 4fe437ea4e undef macros 2023-05-28 12:03:49 -05:00
CPunch e854c5dbb3 fixed GC bug in cundump.c 2023-05-28 11:55:48 -05:00
CPunch c945c56482 these values can be defined at the top of the function 2023-05-28 00:08:28 -05:00
CPunch 89d443d767 formatting changes 2023-05-28 00:03:50 -05:00
CPunch 54a959438b added cdump.[ch] and cundump.[ch] to makefile 2023-05-27 23:17:17 -05:00
CPunch 355842989b cvm.c: added cosmoV_undump 2023-05-27 23:16:47 -05:00
CPunch 45f36e6e87 cdump.c: major refactoring; various fixes 2023-05-27 23:15:58 -05:00
CPunch 819e76b711 cdump.c: fix instruction and line info dumping 2023-05-27 23:15:12 -05:00
CPunch f116efa02c started cundump.c:cosmoD_undump(); minor fixes 2023-05-25 21:12:21 -05:00
CPunch 465f4d5e4a started cdump.c:cosmoD_dump() 2023-05-25 19:41:13 -05:00
13 changed files with 647 additions and 45 deletions

View File

@ -19,6 +19,8 @@ CHDR=\
src/cvm.h\
src/cobj.h\
src/cbaselib.h\
src/cdump.h\
src/cundump.h\
CSRC=\
src/cchunk.c\
@ -33,6 +35,8 @@ CSRC=\
src/cvm.c\
src/cobj.c\
src/cbaselib.c\
src/cdump.c\
src/cundump.c\
main.c\
COBJ=$(CSRC:.c=.o)

View File

@ -1,6 +1,20 @@
# Cosmo
[![AppVeyor](https://ci.appveyor.com/api/projects/status/github/CPunch/Cosmo?svg=true)](https://ci.appveyor.com/project/CPunch/Cosmo)
## Usage
```
Usage: ./bin/cosmo [-clsr] [args]
available options are:
-c <in> <out> compile <in> and dump to <out>
-l <in> load dump from <in>
-s <in...> compile and run <in...> script(s)
-r start the repl
```
## What is a 'cosmo'?
Cosmo is a portable scripting language loosely based off of Lua. Cosmo easily allows the user to extend the language through the use of Proto objects, which describe the behavior of Objects. For example the following is a simple Vector Proto which describes behavior for a Vector-like object.
```lua
@ -39,7 +53,4 @@ end
2 : 1
1 : 2
0 : 3
```
# C API
The Cosmo C API is currently undocumented, however as soon as development has reached a stable state documentation on full language features and the C API will start.
```

View File

@ -25,7 +25,7 @@ install:
- sudo apt install clang cmake -y
build_script:
- make && ./bin/cosmo examples/testsuite.cosmo examples/getters_setters.cosmo
- make && ./bin/cosmo examples/testsuite.cosmo -s examples/getters_setters.cosmo
artifacts:
- path: bin

View File

@ -1,13 +1,13 @@
let object = {
__setter = [
"field1" = function(self, val)
"field1" = func(self, val)
print("setter for field1 called!")
self.x = val
end
],
__getter = [
"field1" = function(self)
"field1" = func(self)
print("getter for field1 called!")
return self.x + 1

169
main.c
View File

@ -1,21 +1,29 @@
#include "cosmo.h"
#include "cbaselib.h"
#include "cchunk.h"
#include "cdebug.h"
#include "cvm.h"
#include "cparse.h"
#include "cbaselib.h"
#include "cdump.h"
#include "cmem.h"
#include "cosmo.h"
#include "cparse.h"
#include "cundump.h"
#include "cvm.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
static bool _ACTIVE = false;
int cosmoB_quitRepl(CState *state, int nargs, CValue *args) {
int cosmoB_quitRepl(CState *state, int nargs, CValue *args)
{
_ACTIVE = false;
return 0; // we don't return anything
}
int cosmoB_input(CState *state, int nargs, CValue *args) {
int cosmoB_input(CState *state, int nargs, CValue *args)
{
// input() accepts the same params as print()!
for (int i = 0; i < nargs; i++) {
CObjString *str = cosmoV_toString(state, args[i]);
@ -26,16 +34,18 @@ int cosmoB_input(CState *state, int nargs, CValue *args) {
char line[1024];
fgets(line, sizeof(line), stdin);
cosmoV_pushRef(state, (CObj*)cosmoO_copyString(state, line, strlen(line)-1)); // -1 for the \n
cosmoV_pushRef(state,
(CObj *)cosmoO_copyString(state, line, strlen(line) - 1)); // -1 for the \n
return 1; // 1 return value
}
static bool interpret(CState *state, const char *script, const char *mod) {
static bool interpret(CState *state, const char *script, const char *mod)
{
bool ret;
// cosmoV_compileString pushes the result onto the stack (COBJ_ERROR or COBJ_CLOSURE)
if (cosmoV_compileString(state, script, mod)) {
if (cosmoV_compileString(state, script, mod)) {
COSMOVMRESULT res = cosmoV_call(state, 0, 0); // 0 args being passed, 0 results expected
if (res == COSMOVM_RUNTIME_ERR)
@ -50,15 +60,11 @@ static bool interpret(CState *state, const char *script, const char *mod) {
return !ret;
}
static void repl() {
static void repl(CState *state)
{
char line[1024];
_ACTIVE = true;
CState *state = cosmoV_newState();
cosmoB_loadLibrary(state);
cosmoB_loadOSLib(state);
cosmoB_loadVM(state);
// add our custom REPL functions
cosmoV_pushString(state, "quit");
cosmoV_pushCFunction(state, cosmoB_quitRepl);
@ -78,12 +84,11 @@ static void repl() {
interpret(state, line, "REPL");
}
cosmoV_freeState(state);
}
static char *readFile(const char* path) {
FILE* file = fopen(path, "rb");
static char *readFile(const char *path)
{
FILE *file = fopen(path, "rb");
if (file == NULL) {
fprintf(stderr, "Could not open file \"%s\".\n", path);
exit(74);
@ -94,7 +99,7 @@ static char *readFile(const char* path) {
size_t fileSize = ftell(file);
rewind(file);
char *buffer = (char*)malloc(fileSize + 1); // make room for the null byte
char *buffer = (char *)malloc(fileSize + 1); // make room for the null byte
if (buffer == NULL) {
fprintf(stderr, "failed to allocate!");
exit(1);
@ -106,7 +111,7 @@ static char *readFile(const char* path) {
printf("failed to read file \"%s\"!\n", path);
exit(74);
}
buffer[bytesRead] = '\0'; // place our null terminator
// close the file handler and return the script buffer
@ -114,12 +119,10 @@ static char *readFile(const char* path) {
return buffer;
}
static bool runFile(const char* fileName) {
static bool runFile(CState *state, const char *fileName)
{
bool ret;
char* script = readFile(fileName);
CState *state = cosmoV_newState();
cosmoB_loadLibrary(state);
cosmoB_loadOSLib(state);
char *script = readFile(fileName);
// add our input() function to the global table
cosmoV_pushString(state, "input");
@ -129,21 +132,119 @@ static bool runFile(const char* fileName) {
ret = interpret(state, script, fileName);
cosmoV_freeState(state);
free(script);
return ret; // let the caller know if the script failed
}
int main(int argc, const char *argv[]) {
if (argc == 1) {
repl();
} else if (argc >= 2) { // they passed a file (or more lol)
for (int i = 1; i < argc; i++) {
if (!runFile(argv[i])) {
int fileWriter(CState *state, const void *data, size_t size, const void *ud)
{
return !fwrite(data, size, 1, (FILE *)ud);
}
int fileReader(CState *state, void *data, size_t size, const void *ud)
{
return fread(data, size, 1, (FILE *)ud) != 1;
}
void compileScript(CState *state, const char *in, const char *out)
{
char *script = readFile(in);
FILE *fout = fopen(out, "wb");
if (cosmoV_compileString(state, script, in)) {
CObjFunction *func = cosmoV_readClosure(*cosmoV_getTop(state, 0))->function;
cosmoD_dump(state, func, fileWriter, (void *)fout);
} else {
cosmoV_pop(state); // pop the error off the stack
cosmoV_printError(state, state->error);
}
free(script);
fclose(fout);
printf("[!] compiled %s to %s successfully!\n", in, out);
}
void loadScript(CState *state, const char *in)
{
FILE *file;
file = fopen(in, "rb");
if (!cosmoV_undump(state, fileReader, file)) {
cosmoV_pop(state); // pop the error off the stack
cosmoV_printError(state, state->error);
return;
};
printf("[!] loaded %s!\n", in);
COSMOVMRESULT res = cosmoV_call(state, 0, 0); // 0 args being passed, 0 results expected
if (res == COSMOVM_RUNTIME_ERR)
cosmoV_printError(state, state->error);
fclose(file);
}
void printUsage(const char *name)
{
printf("Usage: %s [-clsr] [args]\n\n", name);
printf("available options are:\n"
"-c <in> <out>\tcompile <in> and dump to <out>\n"
"-l <in>\t\tload dump from <in>\n"
"-s <in...>\tcompile and run <in...> script(s)\n"
"-r\t\tstart the repl\n\n");
}
int main(int argc, char *const argv[])
{
CState *state = cosmoV_newState();
cosmoB_loadLibrary(state);
cosmoB_loadOSLib(state);
cosmoB_loadVM(state);
int opt;
bool isValid = false;
while ((opt = getopt(argc, argv, "clsr")) != -1) {
switch (opt) {
case 'c':
if (optind >= argc - 1) {
printf("Usage: %s -c <in> <out>\n", argv[0]);
exit(EXIT_FAILURE);
} else {
compileScript(state, argv[optind], argv[optind + 1]);
}
isValid = true;
break;
case 'l':
if (optind >= argc) {
printf("Usage: %s -l <in>\n", argv[0]);
exit(EXIT_FAILURE);
} else {
loadScript(state, argv[optind]);
}
isValid = true;
break;
case 's':
for (int i = optind; i < argc; i++) {
if (!runFile(state, argv[i])) {
printf("failed to run %s!\n", argv[i]);
exit(EXIT_FAILURE);
}
}
isValid = true;
break;
case 'r':
repl(state);
isValid = true;
break;
}
}
if (!isValid) {
printUsage(argv[0]);
}
cosmoV_freeState(state);
return 0;
}

View File

@ -980,6 +980,4 @@ void cosmoB_loadVM(CState *state)
// register "vm" to the global table
cosmoV_register(state, 1);
printf("[WARNING] the vm.* library has been loaded!\n");
}

204
src/cdump.c Normal file
View File

@ -0,0 +1,204 @@
#include "cdump.h"
#include "cdebug.h"
#include "cmem.h"
#include "cobj.h"
#include "cvalue.h"
#include "cvm.h"
typedef struct
{
CState *state;
const void *userData;
cosmo_Writer writer;
int writerStatus;
} DumpState;
static bool writeCValue(DumpState *dstate, CValue val);
#define check(e) \
if (!e) { \
return false; \
}
static void initDumpState(CState *state, DumpState *dstate, cosmo_Writer writer,
const void *userData)
{
dstate->state = state;
dstate->userData = userData;
dstate->writer = writer;
dstate->writerStatus = 0;
}
static bool writeBlock(DumpState *dstate, const void *data, size_t size)
{
if (dstate->writerStatus == 0) {
dstate->writerStatus = dstate->writer(dstate->state, data, size, dstate->userData);
}
return dstate->writerStatus == 0;
}
static bool writeu8(DumpState *dstate, uint8_t d)
{
return writeBlock(dstate, &d, sizeof(uint8_t));
}
static bool writeu32(DumpState *dstate, uint32_t d)
{
return writeBlock(dstate, &d, sizeof(uint32_t));
}
static bool writeSize(DumpState *dstate, size_t d)
{
return writeBlock(dstate, &d, sizeof(size_t));
}
static bool writeVector(DumpState *dstate, const void *data, size_t size, size_t count)
{
check(writeSize(dstate, count));
check(writeBlock(dstate, data, size * count));
return true;
}
static bool writeHeader(DumpState *dstate)
{
check(writeBlock(dstate, COSMO_MAGIC, COSMO_MAGIC_LEN));
/* after the magic, we write some platform information */
check(writeu8(dstate, cosmoD_isBigEndian()));
check(writeu8(dstate, sizeof(cosmo_Number)));
check(writeu8(dstate, sizeof(size_t)));
check(writeu8(dstate, sizeof(int)));
return true;
}
static bool writeCObjString(DumpState *dstate, CObjString *obj)
{
if (obj == NULL) { /* this is in case cobjfunction's name or module strings are null */
check(writeu32(dstate, 0));
return true;
}
/* write string length */
check(writeu32(dstate, obj->length));
/* write string data */
check(writeBlock(dstate, obj->str, obj->length));
return true;
}
static bool writeCObjFunction(DumpState *dstate, CObjFunction *obj)
{
check(writeCObjString(dstate, obj->name));
check(writeCObjString(dstate, obj->module));
check(writeu32(dstate, obj->args));
check(writeu32(dstate, obj->upvals));
check(writeu8(dstate, obj->variadic));
/* write chunk info */
check(writeVector(dstate, obj->chunk.buf, sizeof(uint8_t), obj->chunk.count));
/* write line info */
check(writeVector(dstate, obj->chunk.lineInfo, sizeof(int), obj->chunk.count));
/* write constants */
check(writeSize(dstate, obj->chunk.constants.count));
for (int i = 0; i < obj->chunk.constants.count; i++) {
check(writeCValue(dstate, obj->chunk.constants.values[i]));
}
return true;
}
static bool writeCObj(DumpState *dstate, CObj *obj)
{
/*
we can kind of cheat here since our parser only emits a few very limited CObjs...
CChunks will only ever have the following CObj's in their constant table:
- COBJ_STRING
- COBJ_FUNCTION
the rest of the objects are created during runtime. yay!
*/
CObjType t = cosmoO_readType(obj);
/* write cobj type */
writeu8(dstate, t);
/* write object payload/body */
switch (t) {
case COBJ_STRING:
check(writeCObjString(dstate, (CObjString *)obj));
break;
case COBJ_FUNCTION:
check(writeCObjFunction(dstate, (CObjFunction *)obj));
break;
default:
cosmoV_error(dstate->state, "invalid cobj type: %d", t);
return false;
}
return true;
}
#define WRITE_VAR(dstate, type, expression) \
{ \
type _tmp = expression; \
check(writeBlock(dstate, &_tmp, sizeof(_tmp))); \
break; \
}
static bool writeCValue(DumpState *dstate, CValue val)
{
CosmoType t = GET_TYPE(val);
/* write value type */
writeu8(dstate, t);
/* write value payload/body */
switch (t) {
case COSMO_TNUMBER:
WRITE_VAR(dstate, cosmo_Number, cosmoV_readNumber(val))
case COSMO_TBOOLEAN:
WRITE_VAR(dstate, bool, cosmoV_readBoolean(val))
case COSMO_TREF:
check(writeCObj(dstate, cosmoV_readRef(val)));
break;
case COSMO_TNIL: /* no body */
break;
default:
cosmoV_error(dstate->state, "invalid value type: %d", t);
return false;
}
return true;
}
#undef WRITE_VAR
bool cosmoD_isBigEndian()
{
union
{
uint32_t i;
uint8_t c[4];
} _indxint = {0xDEADB33F};
return _indxint.c[0] == 0xDE;
}
int cosmoD_dump(CState *state, CObjFunction *func, cosmo_Writer writer, const void *userData)
{
DumpState dstate;
initDumpState(state, &dstate, writer, userData);
check(writeHeader(&dstate));
check(writeCObjFunction(&dstate, func));
return dstate.writerStatus;
}

17
src/cdump.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef COSMO_DUMP_H
#define COSMO_DUMP_H
#include "cobj.h"
#include "cosmo.h"
#include <stdio.h>
#define COSMO_MAGIC "COS\x12"
#define COSMO_MAGIC_LEN 4
bool cosmoD_isBigEndian();
/* returns non-zero on error */
int cosmoD_dump(CState *state, CObjFunction *func, cosmo_Writer writer, const void *userData);
#endif

View File

@ -45,6 +45,9 @@ typedef struct CObjClosure CObjClosure;
typedef uint8_t INSTRUCTION;
typedef int (*cosmo_Reader)(CState *state, void *data, size_t size, const void *ud);
typedef int (*cosmo_Writer)(CState *state, const void *data, size_t size, const void *ud);
#define COSMOMAX_UPVALS 80
#define FRAME_MAX 64
#define STACK_MAX (256 * FRAME_MAX)

219
src/cundump.c Normal file
View File

@ -0,0 +1,219 @@
#include "cundump.h"
#include "cchunk.h"
#include "cdump.h"
#include "cmem.h"
#include "cvm.h"
typedef struct
{
CState *state;
const void *userData;
cosmo_Reader reader;
int readerStatus;
} UndumpState;
static bool readCValue(UndumpState *udstate, CValue *val);
#define check(e) \
if (!e) { \
return false; \
}
static void initUndumpState(CState *state, UndumpState *udstate, cosmo_Reader reader,
const void *userData)
{
udstate->state = state;
udstate->userData = userData;
udstate->reader = reader;
udstate->readerStatus = 0;
}
static bool readBlock(UndumpState *udstate, void *data, size_t size)
{
if (udstate->readerStatus == 0) {
/* if reader returns 1, we expect an error was thrown */
udstate->readerStatus = udstate->reader(udstate->state, data, size, udstate->userData);
}
return udstate->readerStatus == 0;
}
static bool readu8(UndumpState *udstate, uint8_t *d)
{
return readBlock(udstate, d, sizeof(uint8_t));
}
static bool readu32(UndumpState *udstate, uint32_t *d)
{
return readBlock(udstate, d, sizeof(uint32_t));
}
static bool readSize(UndumpState *udstate, size_t *d)
{
return readBlock(udstate, d, sizeof(size_t));
}
static bool readVector(UndumpState *udstate, void **data, size_t size, size_t *count)
{
check(readSize(udstate, count));
*data = cosmoM_xmalloc(udstate->state, (*count) * size);
return readBlock(udstate, *data, (*count) * size);
}
#define checku8(udstate, d, tmp) \
check(readu8(udstate, &tmp)); \
if (d != tmp) { \
cosmoV_error(udstate->state, "bad header!"); \
return false; \
}
static bool checkHeader(UndumpState *udstate)
{
char magic[COSMO_MAGIC_LEN];
uint8_t tmp;
/* check header */
check(readBlock(udstate, magic, COSMO_MAGIC_LEN));
if (memcmp(magic, COSMO_MAGIC, COSMO_MAGIC_LEN) != 0) {
cosmoV_error(udstate->state, "bad header!");
return false;
}
/* after the magic, we read some platform information */
checku8(udstate, cosmoD_isBigEndian(), tmp);
checku8(udstate, sizeof(cosmo_Number), tmp);
checku8(udstate, sizeof(size_t), tmp);
checku8(udstate, sizeof(int), tmp);
return true;
}
#undef checku8
static bool readCObjString(UndumpState *udstate, CObjString **str)
{
uint32_t size;
char *data;
check(readu32(udstate, (uint32_t *)&size));
if (size == 0) { /* empty string */
*str = NULL;
return true;
}
data = cosmoM_xmalloc(udstate->state, size + 1);
check(readBlock(udstate, (void *)data, size));
data[size] = '\0'; /* add NULL-terminator */
*str = cosmoO_takeString(udstate->state, data, size);
return true;
}
static bool readCObjFunction(UndumpState *udstate, CObjFunction **func)
{
size_t constants;
CValue val;
*func = cosmoO_newFunction(udstate->state);
/* make sure our GC can see that we're currently using this function (and the values it uses) */
cosmoV_pushRef(udstate->state, (CObj *)*func);
check(readCObjString(udstate, &(*func)->name));
check(readCObjString(udstate, &(*func)->module));
check(readu32(udstate, (uint32_t *)&(*func)->args));
check(readu32(udstate, (uint32_t *)&(*func)->upvals));
check(readu8(udstate, (uint8_t *)&(*func)->variadic));
/* read chunk info */
check(
readVector(udstate, (void **)&(*func)->chunk.buf, sizeof(uint8_t), &(*func)->chunk.count));
check(
readVector(udstate, (void **)&(*func)->chunk.lineInfo, sizeof(int), &(*func)->chunk.count));
/* read constants */
check(readSize(udstate, &constants));
for (int i = 0; i < constants; i++) {
check(readCValue(udstate, &val));
addConstant(udstate->state, &(*func)->chunk, val);
}
/* pop function off stack */
cosmoV_pop(udstate->state);
return true;
}
static bool readCObj(UndumpState *udstate, CObj **obj)
{
uint8_t type;
check(readu8(udstate, &type));
switch (type) {
case COBJ_STRING:
return readCObjString(udstate, (CObjString **)obj);
case COBJ_FUNCTION:
return readCObjFunction(udstate, (CObjFunction **)obj);
default:
cosmoV_error(udstate->state, "unknown object type!");
return false;
}
return true;
}
#define READ_VAR(udstate, val, type, creator) \
{ \
type _tmp; \
check(readBlock(udstate, &_tmp, sizeof(type))); \
*val = creator(_tmp); \
break; \
}
static bool readCValue(UndumpState *udstate, CValue *val)
{
uint8_t t;
check(readu8(udstate, &t));
switch (t) {
case COSMO_TNUMBER:
READ_VAR(udstate, val, cosmo_Number, cosmoV_newNumber)
case COSMO_TBOOLEAN:
READ_VAR(udstate, val, bool, cosmoV_newBoolean)
case COSMO_TREF: {
CObj *obj;
check(readCObj(udstate, (CObj **)&obj));
*val = cosmoV_newRef(obj);
break;
}
case COSMO_TNIL:
*val = cosmoV_newNil();
break;
default:
cosmoV_error(udstate->state, "invalid value type: %d", t);
return false;
}
return true;
}
#undef READ_VAR
#undef check
int cosmoD_undump(CState *state, cosmo_Reader reader, const void *userData, CObjFunction **func)
{
UndumpState udstate;
initUndumpState(state, &udstate, reader, userData);
if (!checkHeader(&udstate)) {
return 1;
}
if (!readCObjFunction(&udstate, func)) {
return 1;
}
cosmoV_pushRef(state, (CObj *)*func);
return udstate.readerStatus;
}

12
src/cundump.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef COSMO_UNDUMP_H
#define COSMO_UNDUMP_H
#include "cobj.h"
#include "cosmo.h"
#include <stdio.h>
/* returns non-zero on error */
int cosmoD_undump(CState *state, cosmo_Reader reader, const void *userData, CObjFunction **func);
#endif

View File

@ -4,6 +4,7 @@
#include "cmem.h"
#include "cparse.h"
#include "cstate.h"
#include "cundump.h"
#include <math.h>
#include <stdarg.h>
@ -30,6 +31,28 @@ COSMO_API void cosmo_insert(CState *state, int indx, CValue val)
state->top++;
}
COSMO_API bool cosmoV_undump(CState *state, cosmo_Reader reader, const void *ud)
{
CObjFunction *func;
if (cosmoD_undump(state, reader, ud, &func)) {
// fail recovery
state->panic = false;
cosmoV_pushRef(state, (CObj *)state->error);
return false;
};
#ifdef VM_DEBUG
disasmChunk(&func->chunk, func->name ? func->name->str : UNNAMEDCHUNK, 0);
#endif
// push function onto the stack so it doesn't it cleaned up by the GC, at the same stack
// location put our closure
cosmoV_pushRef(state, (CObj *)func);
*(cosmoV_getTop(state, 0)) = cosmoV_newRef(cosmoO_newClosure(state, func));
return true;
}
COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *name)
{
CObjFunction *func;
@ -46,7 +69,7 @@ COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *
return true;
}
// fail
// fail recovery
state->panic = false;
cosmoV_pushRef(state, (CObj *)state->error);
return false;

View File

@ -38,7 +38,7 @@ COSMO_API void cosmo_insert(CState *state, int indx, CValue val);
COSMO_API bool cosmoV_registerProtoObject(CState *state, CObjType objType, CObjObject *obj);
/*
compiles string into a <closure>, if successful, <closure> will be pushed onto the stack
compiles string into a <closure>. if successful, <closure> will be pushed onto the stack
otherwise the <error> will be pushed.
returns:
@ -47,6 +47,16 @@ COSMO_API bool cosmoV_registerProtoObject(CState *state, CObjType objType, CObjO
*/
COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *name);
/*
loads a <closure> from a dump. if successful, <closure> will be pushed onto the stack
otherwise the <error> will be pushed.
returns:
false : <error> is at the top of the stack
true : <closure> is at the top of the stack
*/
COSMO_API bool cosmoV_undump(CState *state, cosmo_Reader reader, const void *ud);
/*
expects object to be pushed, then the key.