mirror of
https://github.com/CPunch/Cosmo.git
synced 2025-10-21 16:30:18 +00:00
Compare commits
14 Commits
7f5e3ae8dc
...
main
Author | SHA1 | Date | |
---|---|---|---|
5711ca218e | |||
5cd3049d66 | |||
cd37cfdae5 | |||
e0455902b0 | |||
43d79a456e | |||
105a3d70c3 | |||
93f3ae1106 | |||
4816e64612 | |||
0df56bd42a | |||
e7b2d7d833 | |||
39060a67e9 | |||
5296495e47 | |||
a337e26229 | |||
b7bb0773b1 |
10
README.md
10
README.md
@@ -1,7 +1,4 @@
|
|||||||
# Cosmo
|
# Cosmo
|
||||||
[](https://github.com/CPunch/Cosmo/actions/workflows/check_build.yaml)
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```
|
```
|
||||||
Usage: ./bin/cosmo [-clsr] [args]
|
Usage: ./bin/cosmo [-clsr] [args]
|
||||||
@@ -13,6 +10,13 @@ available options are:
|
|||||||
-r start the repl
|
-r start the repl
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://github.com/CPunch/Cosmo/actions/workflows/check_build.yaml"><img src="https://github.com/CPunch/Cosmo/actions/workflows/check_build.yaml/badge.svg?branch=main" alt="Workflow"></a>
|
||||||
|
<a href="https://github.com/CPunch/Cosmo/blob/main/LICENSE.md"><img src="https://img.shields.io/github/license/CPunch/Cosmo" alt="License"></a>
|
||||||
|
<br>
|
||||||
|
<a href="https://asciinema.org/a/629355" target="_blank"><img src="https://asciinema.org/a/629355.svg" /></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
## What is a 'cosmo'?
|
## 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.
|
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.
|
||||||
|
25
main.c
25
main.c
@@ -50,13 +50,24 @@ static bool interpret(CState *state, const char *script, const char *mod)
|
|||||||
|
|
||||||
// cosmoV_compileString pushes the result onto the stack (COBJ_ERROR or COBJ_CLOSURE)
|
// 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)) {
|
||||||
// 0 args being passed, 0 results expected
|
cosmoG_disassemble(cosmoV_readClosure(*cosmoV_getTop(state, 0)));
|
||||||
if (!cosmoV_pcall(state, 0, 0)) {
|
if (!cosmoV_pcall(state, 0, 1)) {
|
||||||
cosmoV_printError(state, cosmoV_readError(*cosmoV_pop(state)));
|
cosmoV_printBacktrace(state, cosmoV_readError(*cosmoV_pop(state)));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the result is nil, we don't print it
|
||||||
|
if (IS_NIL(*cosmoV_getTop(state, 0))) {
|
||||||
|
cosmoV_pop(state);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, we print the result
|
||||||
|
cosmoV_printValue(*cosmoV_getTop(state, 0));
|
||||||
|
printf("\n");
|
||||||
|
cosmoV_pop(state);
|
||||||
} else {
|
} else {
|
||||||
cosmoV_printError(state, cosmoV_readError(*cosmoV_pop(state)));
|
cosmoV_printBacktrace(state, cosmoV_readError(*cosmoV_pop(state)));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +169,7 @@ void compileScript(CState *state, const char *in, const char *out)
|
|||||||
CObjFunction *func = cosmoV_readClosure(*cosmoV_getTop(state, 0))->function;
|
CObjFunction *func = cosmoV_readClosure(*cosmoV_getTop(state, 0))->function;
|
||||||
cosmoD_dump(state, func, fileWriter, (void *)fout);
|
cosmoD_dump(state, func, fileWriter, (void *)fout);
|
||||||
} else {
|
} else {
|
||||||
cosmoV_printError(state, cosmoV_readError(*cosmoV_pop(state)));
|
cosmoV_printBacktrace(state, cosmoV_readError(*cosmoV_pop(state)));
|
||||||
}
|
}
|
||||||
|
|
||||||
free(script);
|
free(script);
|
||||||
@@ -171,13 +182,13 @@ void loadScript(CState *state, const char *in)
|
|||||||
{
|
{
|
||||||
FILE *file = fopen(in, "rb");
|
FILE *file = fopen(in, "rb");
|
||||||
if (!cosmoV_undump(state, fileReader, file)) {
|
if (!cosmoV_undump(state, fileReader, file)) {
|
||||||
cosmoV_printError(state, cosmoV_readError(*cosmoV_pop(state)));
|
cosmoV_printBacktrace(state, cosmoV_readError(*cosmoV_pop(state)));
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
printf("[!] loaded %s!\n", in);
|
printf("[!] loaded %s!\n", in);
|
||||||
if (!cosmoV_pcall(state, 0, 0))
|
if (!cosmoV_pcall(state, 0, 0))
|
||||||
cosmoV_printError(state, cosmoV_readError(*cosmoV_pop(state)));
|
cosmoV_printBacktrace(state, cosmoV_readError(*cosmoV_pop(state)));
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,7 @@ int cosmoB_print(CState *state, int nargs, CValue *args)
|
|||||||
CObjString *str = cosmoV_toString(state, args[i]);
|
CObjString *str = cosmoV_toString(state, args[i]);
|
||||||
printf("%s", cosmoO_readCString(str));
|
printf("%s", cosmoO_readCString(str));
|
||||||
} else { // else, thats pretty expensive for primitives, just print the raw value
|
} else { // else, thats pretty expensive for primitives, just print the raw value
|
||||||
printValue(args[i]);
|
cosmoV_printValue(args[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -182,6 +182,32 @@ int cosmoB_ogetProto(CState *state, int nargs, CValue *args)
|
|||||||
return 1; // 1 result
|
return 1; // 1 result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cosmoB_ogetKeys(CState *state, int nargs, CValue *args)
|
||||||
|
{
|
||||||
|
if (nargs != 1)
|
||||||
|
cosmoV_error(state, "Expected 1 argument, got %d!", nargs);
|
||||||
|
|
||||||
|
if (!IS_OBJECT(args[0])) {
|
||||||
|
cosmoV_typeError(state, "object.__keys", "<object>", "%s", cosmoV_typeStr(args[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// push keys
|
||||||
|
CObjObject *obj = cosmoV_readObject(args[0]);
|
||||||
|
int cap = cosmoT_getCapacity(&obj->tbl);
|
||||||
|
int indx = 0;
|
||||||
|
for (int i = 0; i < cap; i++) {
|
||||||
|
CTableEntry *entry = &obj->tbl.table[i];
|
||||||
|
if (IS_NIL(entry->key))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cosmoV_pushNumber(state, indx++);
|
||||||
|
cosmoV_pushValue(state, entry->key);
|
||||||
|
}
|
||||||
|
|
||||||
|
cosmoV_makeTable(state, indx);
|
||||||
|
return 1; // 1 result
|
||||||
|
}
|
||||||
|
|
||||||
int cosmoB_oisChild(CState *state, int nargs, CValue *args)
|
int cosmoB_oisChild(CState *state, int nargs, CValue *args)
|
||||||
{
|
{
|
||||||
if (nargs != 2) {
|
if (nargs != 2) {
|
||||||
@@ -203,9 +229,9 @@ int cosmoB_oisChild(CState *state, int nargs, CValue *args)
|
|||||||
|
|
||||||
COSMO_API void cosmoB_loadObjLib(CState *state)
|
COSMO_API void cosmoB_loadObjLib(CState *state)
|
||||||
{
|
{
|
||||||
const char *identifiers[] = {"ischild"};
|
const char *identifiers[] = {"ischild", "keys"};
|
||||||
|
|
||||||
CosmoCFunction objLib[] = {cosmoB_oisChild};
|
CosmoCFunction objLib[] = {cosmoB_oisChild, cosmoB_ogetKeys};
|
||||||
|
|
||||||
// make object library object
|
// make object library object
|
||||||
cosmoV_pushString(state, "object");
|
cosmoV_pushString(state, "object");
|
||||||
@@ -213,7 +239,7 @@ COSMO_API void cosmoB_loadObjLib(CState *state)
|
|||||||
// make __getter object for debug proto
|
// make __getter object for debug proto
|
||||||
cosmoV_pushString(state, "__getter");
|
cosmoV_pushString(state, "__getter");
|
||||||
|
|
||||||
// key & value pair
|
// key & value pairs
|
||||||
cosmoV_pushString(state, "__proto"); // key
|
cosmoV_pushString(state, "__proto"); // key
|
||||||
cosmoV_pushCFunction(state, cosmoB_ogetProto); // value
|
cosmoV_pushCFunction(state, cosmoB_ogetProto); // value
|
||||||
|
|
||||||
@@ -269,14 +295,14 @@ int fileB_read(CState *state, int nargs, CValue *args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allocate a buffer for the read data
|
// allocate a buffer for the read data
|
||||||
buffer = cosmoM_xmalloc(state, length + 1);
|
buffer = cosmoM_xmalloc(state, (size_t)length + 1);
|
||||||
|
|
||||||
// read the data
|
// read the data
|
||||||
fread(buffer, sizeof(char), length, file);
|
fread(buffer, sizeof(char), (size_t)length, file);
|
||||||
buffer[(int)length] = '\0'; // write the NULL terminator
|
buffer[(int)length] = '\0'; // write the NULL terminator
|
||||||
|
|
||||||
// push the read data
|
// push the read data
|
||||||
temp = cosmoV_newRef(cosmoO_takeString(state, buffer, length));
|
temp = cosmoV_newRef(cosmoO_takeString(state, buffer, (size_t)length));
|
||||||
cosmoV_pushValue(state, temp);
|
cosmoV_pushValue(state, temp);
|
||||||
} else if (IS_STRING(args[1])) {
|
} else if (IS_STRING(args[1])) {
|
||||||
if (strcmp(cosmoV_readCString(args[1]), "a") == 0) {
|
if (strcmp(cosmoV_readCString(args[1]), "a") == 0) {
|
||||||
@@ -290,17 +316,17 @@ int fileB_read(CState *state, int nargs, CValue *args)
|
|||||||
fseek(file, 0, SEEK_SET);
|
fseek(file, 0, SEEK_SET);
|
||||||
|
|
||||||
// allocate a buffer for the read data
|
// allocate a buffer for the read data
|
||||||
buffer = cosmoM_xmalloc(state, length + 1);
|
buffer = cosmoM_xmalloc(state, (size_t)length + 1);
|
||||||
|
|
||||||
// read the data
|
// read the data
|
||||||
fread(buffer, sizeof(char), length, file);
|
fread(buffer, sizeof(char), (size_t)length, file);
|
||||||
buffer[length] = '\0'; // write the NULL terminator
|
buffer[length] = '\0'; // write the NULL terminator
|
||||||
|
|
||||||
// push the read data
|
// push the read data
|
||||||
temp = cosmoV_newRef(cosmoO_takeString(state, buffer, length));
|
temp = cosmoV_newRef(cosmoO_takeString(state, buffer, (size_t)length));
|
||||||
cosmoV_pushValue(state, temp);
|
cosmoV_pushValue(state, temp);
|
||||||
} else {
|
} else {
|
||||||
cosmoV_error(state, "file:read() expected \"a\" or <number>, got %s!",
|
cosmoV_error(state, "file:read() expected \"a\" or <number>, got \"%s\"!",
|
||||||
cosmoV_readCString(args[1]));
|
cosmoV_readCString(args[1]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -311,7 +337,8 @@ int fileB_read(CState *state, int nargs, CValue *args)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fileB_write(CState *state, int nargs, CValue *args) {
|
int fileB_write(CState *state, int nargs, CValue *args)
|
||||||
|
{
|
||||||
CObjObject *fileObj;
|
CObjObject *fileObj;
|
||||||
CObjString *str;
|
CObjString *str;
|
||||||
FILE *file;
|
FILE *file;
|
||||||
@@ -339,14 +366,14 @@ int fileB_write(CState *state, int nargs, CValue *args) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fileB_gc(CState *state, int nargs, CValue *args) {
|
int fileB_gc(CState *state, int nargs, CValue *args)
|
||||||
|
{
|
||||||
if (nargs != 1) {
|
if (nargs != 1) {
|
||||||
cosmoV_error(state, "file: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)) {
|
if (!cosmoV_isValueUserType(state, args[0], COSMO_USER_FILE)) {
|
||||||
cosmoV_typeError(state, "file:__gc()", "<file>", "%s",
|
cosmoV_typeError(state, "file:__gc()", "<file>", "%s", cosmoV_typeStr(args[0]));
|
||||||
cosmoV_typeStr(args[0]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CObjObject *fileObj = cosmoV_readObject(args[0]);
|
CObjObject *fileObj = cosmoV_readObject(args[0]);
|
||||||
@@ -385,7 +412,8 @@ int cosmoB_osOpen(CState *state, int nargs, CValue *args)
|
|||||||
|
|
||||||
if (nargs == 2) {
|
if (nargs == 2) {
|
||||||
if (!IS_STRING(args[1])) {
|
if (!IS_STRING(args[1])) {
|
||||||
cosmoV_typeError(state, "os.open()", "<string>, <string>", "%s, %s", cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]));
|
cosmoV_typeError(state, "os.open()", "<string>, <string>", "%s, %s",
|
||||||
|
cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
mode = cosmoV_readCString(args[1]);
|
mode = cosmoV_readCString(args[1]);
|
||||||
|
@@ -62,7 +62,7 @@ static int constInstruction(const char *name, CChunk *chunk, int offset)
|
|||||||
printf("%-16s [%05d] - ", name, index);
|
printf("%-16s [%05d] - ", name, index);
|
||||||
CValue val = chunk->constants.values[index];
|
CValue val = chunk->constants.values[index];
|
||||||
|
|
||||||
printValue(val);
|
cosmoV_printValue(val);
|
||||||
|
|
||||||
return offset + 1 + (sizeof(uint16_t) / sizeof(INSTRUCTION)); // consume opcode + uint
|
return offset + 1 + (sizeof(uint16_t) / sizeof(INSTRUCTION)); // consume opcode + uint
|
||||||
}
|
}
|
||||||
@@ -128,7 +128,7 @@ int disasmInstr(CChunk *chunk, int offset, int indent)
|
|||||||
CObjFunction *cobjFunc = (CObjFunction *)cosmoV_readRef(val);
|
CObjFunction *cobjFunc = (CObjFunction *)cosmoV_readRef(val);
|
||||||
offset += 3; // we consumed the opcode + u16
|
offset += 3; // we consumed the opcode + u16
|
||||||
|
|
||||||
printValue(val);
|
cosmoV_printValue(val);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
// list the upvalues/locals that are captured
|
// list the upvalues/locals that are captured
|
||||||
@@ -223,3 +223,8 @@ int disasmInstr(CChunk *chunk, int offset, int indent)
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cosmoG_disassemble(CObjClosure *closure)
|
||||||
|
{
|
||||||
|
disasmChunk(&closure->function->chunk, closure->function->name == NULL ? UNNAMEDCHUNK : closure->function->name->str, 0);
|
||||||
|
}
|
@@ -2,10 +2,13 @@
|
|||||||
#define CDEBUG_H
|
#define CDEBUG_H
|
||||||
|
|
||||||
#include "cchunk.h"
|
#include "cchunk.h"
|
||||||
|
#include "cobj.h"
|
||||||
|
|
||||||
COSMO_API void disasmChunk(CChunk *chunk, const char *name, int indent);
|
COSMO_API void disasmChunk(CChunk *chunk, const char *name, int indent);
|
||||||
COSMO_API int disasmInstr(CChunk *chunk, int offset, int indent);
|
COSMO_API int disasmInstr(CChunk *chunk, int offset, int indent);
|
||||||
|
|
||||||
void printIndent(int indent);
|
void printIndent(int indent);
|
||||||
|
|
||||||
|
COSMO_API void cosmoG_disassemble(CObjClosure *closure);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -231,11 +231,11 @@ static void traceGrays(CState *state)
|
|||||||
|
|
||||||
static void sweep(CState *state)
|
static void sweep(CState *state)
|
||||||
{
|
{
|
||||||
CObj *prev = NULL;
|
CObj *prev = NULL, *object = state->objects;
|
||||||
CObj *object = state->objects;
|
|
||||||
while (object != NULL) {
|
while (object != NULL) {
|
||||||
if (object->isMarked) { // skip over it
|
if (object->isMarked) { // skip over it
|
||||||
object->isMarked = false; // rest to white
|
object->isMarked = false; // reset to white
|
||||||
prev = object;
|
prev = object;
|
||||||
object = object->next;
|
object = object->next;
|
||||||
} else { // free it!
|
} else { // free it!
|
||||||
@@ -259,7 +259,6 @@ static void sweep(CState *state)
|
|||||||
cosmoV_call(state, 1, 0);
|
cosmoV_call(state, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cosmoO_free(state, oldObj);
|
cosmoO_free(state, oldObj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -493,7 +493,6 @@ 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))
|
||||||
@@ -716,13 +715,13 @@ void printObject(CObj *o)
|
|||||||
case COBJ_ERROR: {
|
case COBJ_ERROR: {
|
||||||
CObjError *err = (CObjError *)o;
|
CObjError *err = (CObjError *)o;
|
||||||
printf("%p -> ", (void *)o);
|
printf("%p -> ", (void *)o);
|
||||||
printValue(err->err);
|
cosmoV_printValue(err->err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case COBJ_METHOD: {
|
case COBJ_METHOD: {
|
||||||
CObjMethod *method = (CObjMethod *)o;
|
CObjMethod *method = (CObjMethod *)o;
|
||||||
printf("%p -> ", (void *)method);
|
printf("%p -> ", (void *)method);
|
||||||
printValue(method->func);
|
cosmoV_printValue(method->func);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case COBJ_CLOSURE: {
|
case COBJ_CLOSURE: {
|
||||||
@@ -734,7 +733,7 @@ void printObject(CObj *o)
|
|||||||
case COBJ_UPVALUE: {
|
case COBJ_UPVALUE: {
|
||||||
CObjUpval *upval = (CObjUpval *)o;
|
CObjUpval *upval = (CObjUpval *)o;
|
||||||
printf("%p -> ", (void *)upval->val);
|
printf("%p -> ", (void *)upval->val);
|
||||||
printValue(*upval->val);
|
cosmoV_printValue(*upval->val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@@ -55,7 +55,7 @@ struct CObjError
|
|||||||
CCallFrame *frames;
|
CCallFrame *frames;
|
||||||
int frameCount;
|
int frameCount;
|
||||||
int line; // reserved for parser errors
|
int line; // reserved for parser errors
|
||||||
bool parserError; // if true, cosmoV_printError will format the error to the lexer
|
bool parserError; // if true, cosmoV_printBacktrace will format the error to the lexer
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CObjObject
|
struct CObjObject
|
||||||
|
47
src/cparse.c
47
src/cparse.c
@@ -102,9 +102,7 @@ static int expressionPrecedence(CParseState *pstate, int needed, Precedence prec
|
|||||||
// returns # of pushed values onto the stack
|
// returns # of pushed values onto the stack
|
||||||
static int expression(CParseState *pstate, int needed, bool forceNeeded);
|
static int expression(CParseState *pstate, int needed, bool forceNeeded);
|
||||||
static void statement(CParseState *pstate);
|
static void statement(CParseState *pstate);
|
||||||
static void declaration(CParseState *pstate);
|
|
||||||
static void parseFunction(CParseState *pstate, FunctionType type);
|
static void parseFunction(CParseState *pstate, FunctionType type);
|
||||||
static void expressionStatement(CParseState *pstate);
|
|
||||||
static ParseRule *getRule(CTokenType type);
|
static ParseRule *getRule(CTokenType type);
|
||||||
static CObjFunction *endCompiler(CParseState *pstate);
|
static CObjFunction *endCompiler(CParseState *pstate);
|
||||||
|
|
||||||
@@ -592,8 +590,6 @@ static void group(CParseState *pstate, bool canAssign, Precedence prec)
|
|||||||
consume(pstate, TOKEN_RIGHT_PAREN, "Expected ')'");
|
consume(pstate, TOKEN_RIGHT_PAREN, "Expected ')'");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WRITE_GLOBAL_OP(pstate, op, arg)
|
|
||||||
|
|
||||||
static void _etterAB(CParseState *pstate, uint8_t a, int b, bool isGlobal)
|
static void _etterAB(CParseState *pstate, uint8_t a, int b, bool isGlobal)
|
||||||
{
|
{
|
||||||
writeu8(pstate, a);
|
writeu8(pstate, a);
|
||||||
@@ -1101,18 +1097,19 @@ static ParseRule *getRule(CTokenType type)
|
|||||||
// returns true if it got past the first token (aka prefix wasn't null)
|
// returns true if it got past the first token (aka prefix wasn't null)
|
||||||
static bool parsePrecedence(CParseState *pstate, Precedence prec)
|
static bool parsePrecedence(CParseState *pstate, Precedence prec)
|
||||||
{
|
{
|
||||||
|
bool canAssign;
|
||||||
|
ParseFunc prefix, infix;
|
||||||
|
|
||||||
advance(pstate);
|
advance(pstate);
|
||||||
|
if ((prefix = getRule(pstate->previous.type)->prefix) == NULL)
|
||||||
ParseFunc prefix = getRule(pstate->previous.type)->prefix;
|
|
||||||
|
|
||||||
if (prefix == NULL)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool canAssign = prec <= PREC_ASSIGNMENT;
|
canAssign = prec <= PREC_ASSIGNMENT;
|
||||||
prefix(pstate, canAssign, prec);
|
prefix(pstate, canAssign, prec);
|
||||||
|
|
||||||
while (prec <= getRule(pstate->current.type)->level) {
|
while (prec <= getRule(pstate->current.type)->level) {
|
||||||
ParseFunc infix = getRule(pstate->current.type)->infix;
|
if ((infix = getRule(pstate->current.type)->infix) == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
advance(pstate);
|
advance(pstate);
|
||||||
infix(pstate, canAssign, prec);
|
infix(pstate, canAssign, prec);
|
||||||
}
|
}
|
||||||
@@ -1266,7 +1263,7 @@ static void endScope(CParseState *pstate)
|
|||||||
static void block(CParseState *pstate)
|
static void block(CParseState *pstate)
|
||||||
{
|
{
|
||||||
while (!check(pstate, TOKEN_END) && !check(pstate, TOKEN_EOF) && !check(pstate, TOKEN_ERROR)) {
|
while (!check(pstate, TOKEN_END) && !check(pstate, TOKEN_EOF) && !check(pstate, TOKEN_ERROR)) {
|
||||||
declaration(pstate);
|
statement(pstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
consume(pstate, TOKEN_END, "'end' expected to end block.'");
|
consume(pstate, TOKEN_END, "'end' expected to end block.'");
|
||||||
@@ -1323,7 +1320,7 @@ static void ifStatement(CParseState *pstate)
|
|||||||
while (!check(pstate, TOKEN_END) && !check(pstate, TOKEN_ELSE) &&
|
while (!check(pstate, TOKEN_END) && !check(pstate, TOKEN_ELSE) &&
|
||||||
!check(pstate, TOKEN_ELSEIF) && !check(pstate, TOKEN_EOF) &&
|
!check(pstate, TOKEN_ELSEIF) && !check(pstate, TOKEN_EOF) &&
|
||||||
!check(pstate, TOKEN_ERROR)) {
|
!check(pstate, TOKEN_ERROR)) {
|
||||||
declaration(pstate);
|
statement(pstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
endScope(pstate);
|
endScope(pstate);
|
||||||
@@ -1473,10 +1470,10 @@ static void functionDeclaration(CParseState *pstate)
|
|||||||
|
|
||||||
static void returnStatement(CParseState *pstate)
|
static void returnStatement(CParseState *pstate)
|
||||||
{
|
{
|
||||||
if (pstate->compiler->type != FTYPE_FUNCTION && pstate->compiler->type != FTYPE_METHOD) {
|
// if (pstate->compiler->type != FTYPE_FUNCTION && pstate->compiler->type != FTYPE_METHOD) {
|
||||||
error(pstate, "Expected 'return' in function!");
|
// error(pstate, "Expected 'return' in function!");
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (blockFollow(pstate->current)) { // does this return have a value
|
if (blockFollow(pstate->current)) { // does this return have a value
|
||||||
writeu8(pstate, OP_NIL);
|
writeu8(pstate, OP_NIL);
|
||||||
@@ -1591,7 +1588,7 @@ static void forLoop(CParseState *pstate)
|
|||||||
|
|
||||||
// parse initializer
|
// parse initializer
|
||||||
if (!match(pstate, TOKEN_EOS)) {
|
if (!match(pstate, TOKEN_EOS)) {
|
||||||
expressionStatement(pstate);
|
statement(pstate);
|
||||||
consume(pstate, TOKEN_EOS, "Expected ';' after initializer");
|
consume(pstate, TOKEN_EOS, "Expected ';' after initializer");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1707,7 +1704,7 @@ static int expression(CParseState *pstate, int needed, bool forceNeeded)
|
|||||||
forceNeeded); // anything above assignments are an expression
|
forceNeeded); // anything above assignments are an expression
|
||||||
}
|
}
|
||||||
|
|
||||||
static void expressionStatement(CParseState *pstate)
|
static void statement(CParseState *pstate)
|
||||||
{
|
{
|
||||||
int savedPushed = pstate->compiler->pushedValues;
|
int savedPushed = pstate->compiler->pushedValues;
|
||||||
|
|
||||||
@@ -1762,16 +1759,6 @@ static void expressionStatement(CParseState *pstate)
|
|||||||
alignStack(pstate, savedPushed);
|
alignStack(pstate, savedPushed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void statement(CParseState *pstate)
|
|
||||||
{
|
|
||||||
expressionStatement(pstate);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void declaration(CParseState *pstate)
|
|
||||||
{
|
|
||||||
statement(pstate);
|
|
||||||
}
|
|
||||||
|
|
||||||
static CObjFunction *endCompiler(CParseState *pstate)
|
static CObjFunction *endCompiler(CParseState *pstate)
|
||||||
{
|
{
|
||||||
popLocals(pstate, pstate->compiler->scopeDepth + 1); // remove the locals from other scopes
|
popLocals(pstate, pstate->compiler->scopeDepth + 1); // remove the locals from other scopes
|
||||||
@@ -1796,7 +1783,7 @@ CObjFunction *cosmoP_compileString(CState *state, const char *source, const char
|
|||||||
advance(&parser);
|
advance(&parser);
|
||||||
|
|
||||||
while (!match(&parser, TOKEN_EOF)) {
|
while (!match(&parser, TOKEN_EOF)) {
|
||||||
declaration(&parser);
|
statement(&parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
consume(&parser, TOKEN_EOF, "End of file expected!");
|
consume(&parser, TOKEN_EOF, "End of file expected!");
|
||||||
|
11
src/cstate.c
11
src/cstate.c
@@ -168,7 +168,8 @@ void cosmoV_addRegistry(CState *state, int pairs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// expects 1 key on the stack, pushes result
|
// expects 1 key on the stack, pushes result
|
||||||
void cosmoV_getRegistry(CState *state) {
|
void cosmoV_getRegistry(CState *state)
|
||||||
|
{
|
||||||
CValue key = *cosmoV_pop(state);
|
CValue key = *cosmoV_pop(state);
|
||||||
CValue val;
|
CValue val;
|
||||||
|
|
||||||
@@ -179,12 +180,14 @@ void cosmoV_getRegistry(CState *state) {
|
|||||||
cosmoV_pushValue(state, val);
|
cosmoV_pushValue(state, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cosmoV_setProto(CState *state) {
|
void cosmoV_setProto(CState *state)
|
||||||
|
{
|
||||||
StkPtr objVal = cosmoV_getTop(state, 1);
|
StkPtr objVal = cosmoV_getTop(state, 1);
|
||||||
StkPtr protoVal = cosmoV_getTop(state, 0);
|
StkPtr protoVal = cosmoV_getTop(state, 0);
|
||||||
|
|
||||||
if (!IS_REF(*objVal) || !IS_OBJECT(*protoVal)) {
|
if (!IS_REF(*objVal) || !IS_OBJECT(*protoVal)) {
|
||||||
cosmoV_error(state, "cannot set %s to proto of type %s", cosmoV_typeStr(*objVal), cosmoV_typeStr(*protoVal));
|
cosmoV_error(state, "cannot set %s to proto of type %s", cosmoV_typeStr(*objVal),
|
||||||
|
cosmoV_typeStr(*protoVal));
|
||||||
}
|
}
|
||||||
|
|
||||||
// actually set the protos
|
// actually set the protos
|
||||||
@@ -200,7 +203,7 @@ void cosmoV_printStack(CState *state)
|
|||||||
printf("==== [[ stack dump ]] ====\n");
|
printf("==== [[ stack dump ]] ====\n");
|
||||||
for (CValue *top = state->top - 1; top >= state->stack; top--) {
|
for (CValue *top = state->top - 1; top >= state->stack; top--) {
|
||||||
printf("%d: ", (int)(top - state->stack));
|
printf("%d: ", (int)(top - state->stack));
|
||||||
printValue(*top);
|
cosmoV_printValue(*top);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -69,6 +69,8 @@ static uint32_t getObjectHash(CObj *obj)
|
|||||||
switch (obj->type) {
|
switch (obj->type) {
|
||||||
case COBJ_STRING:
|
case COBJ_STRING:
|
||||||
return ((CObjString *)obj)->hash;
|
return ((CObjString *)obj)->hash;
|
||||||
|
case COBJ_CFUNCTION:
|
||||||
|
return (uint32_t)((CObjCFunction *)obj)->cfunc;
|
||||||
default:
|
default:
|
||||||
return (uint32_t)obj; // just "hash" the pointer
|
return (uint32_t)obj; // just "hash" the pointer
|
||||||
}
|
}
|
||||||
@@ -286,9 +288,9 @@ void cosmoT_printTable(CTable *tbl, const char *name)
|
|||||||
for (int i = 0; i < cap; i++) {
|
for (int i = 0; i < cap; i++) {
|
||||||
CTableEntry *entry = &tbl->table[i];
|
CTableEntry *entry = &tbl->table[i];
|
||||||
if (!(IS_NIL(entry->key))) {
|
if (!(IS_NIL(entry->key))) {
|
||||||
printValue(entry->key);
|
cosmoV_printValue(entry->key);
|
||||||
printf(" - ");
|
printf(" - ");
|
||||||
printValue(entry->val);
|
cosmoV_printValue(entry->val);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -101,7 +101,7 @@ const char *cosmoV_typeStr(CValue val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void printValue(CValue val)
|
void cosmoV_printValue(CValue val)
|
||||||
{
|
{
|
||||||
switch (GET_TYPE(val)) {
|
switch (GET_TYPE(val)) {
|
||||||
case COSMO_TNUMBER:
|
case COSMO_TNUMBER:
|
||||||
|
@@ -119,7 +119,7 @@ void initValArray(CState *state, CValueArray *val, size_t startCapacity);
|
|||||||
void cleanValArray(CState *state, CValueArray *array); // cleans array
|
void cleanValArray(CState *state, CValueArray *array); // cleans array
|
||||||
void appendValArray(CState *state, CValueArray *array, CValue val);
|
void appendValArray(CState *state, CValueArray *array, CValue val);
|
||||||
|
|
||||||
void printValue(CValue val);
|
void cosmoV_printValue(CValue val);
|
||||||
COSMO_API bool cosmoV_equal(CState *state, CValue valA, CValue valB);
|
COSMO_API bool cosmoV_equal(CState *state, CValue valA, CValue valB);
|
||||||
COSMO_API CObjString *cosmoV_toString(CState *state, CValue val);
|
COSMO_API CObjString *cosmoV_toString(CState *state, CValue val);
|
||||||
COSMO_API cosmo_Number cosmoV_toNumber(CState *state, CValue val);
|
COSMO_API cosmo_Number cosmoV_toNumber(CState *state, CValue val);
|
||||||
|
10
src/cvm.c
10
src/cvm.c
@@ -78,7 +78,7 @@ bool cosmoV_compileString(CState *state, const char *src, const char *name)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cosmoV_printError(CState *state, CObjError *err)
|
void cosmoV_printBacktrace(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++) {
|
||||||
@@ -129,7 +129,7 @@ void cosmoV_throw(CState *state)
|
|||||||
} else {
|
} else {
|
||||||
cosmoV_pushValue(state, val);
|
cosmoV_pushValue(state, val);
|
||||||
fprintf(stderr, "Unhandled panic! ");
|
fprintf(stderr, "Unhandled panic! ");
|
||||||
cosmoV_printError(state, error);
|
cosmoV_printBacktrace(state, error);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -340,7 +340,7 @@ void callCValue(CState *state, CValue func, int args, int nresults, int offset)
|
|||||||
#ifdef VM_DEBUG
|
#ifdef VM_DEBUG
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printIndent(state->frameCount - 1);
|
printIndent(state->frameCount - 1);
|
||||||
printValue(func);
|
cosmoV_printValue(func);
|
||||||
printf("(%d args)\n", args);
|
printf("(%d args)\n", args);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -582,7 +582,8 @@ void cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cosmoV_isValueUserType(CState *state, CValue val, int userType) {
|
bool cosmoV_isValueUserType(CState *state, CValue val, int userType)
|
||||||
|
{
|
||||||
if (!IS_OBJECT(val)) {
|
if (!IS_OBJECT(val)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -855,7 +856,6 @@ int cosmoV_execute(CState *state)
|
|||||||
CObjObject *proto = cosmoO_grabProto(obj);
|
CObjObject *proto = cosmoO_grabProto(obj);
|
||||||
CValue val = cosmoV_newNil(); // 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
|
||||||
cosmoO_indexObject(state, proto, *key, &val);
|
cosmoO_indexObject(state, proto, *key, &val);
|
||||||
|
@@ -33,7 +33,7 @@ COSMO_API CObjObject *cosmoV_makeObject(CState *state, int pairs);
|
|||||||
COSMO_API void cosmoV_makeTable(CState *state, int pairs);
|
COSMO_API void cosmoV_makeTable(CState *state, int pairs);
|
||||||
COSMO_API void cosmoV_concat(CState *state, int vals);
|
COSMO_API void cosmoV_concat(CState *state, int vals);
|
||||||
COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...);
|
COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...);
|
||||||
COSMO_API void cosmoV_printError(CState *state, CObjError *err);
|
COSMO_API void cosmoV_printBacktrace(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 cosmoV_insert(CState *state, int indx, CValue val);
|
COSMO_API void cosmoV_insert(CState *state, int indx, CValue val);
|
||||||
@@ -72,7 +72,8 @@ 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 object, key & value
|
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);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user