Compare commits

..

9 Commits

Author SHA1 Message Date
5711ca218e improved readme, added asciinema demo 2023-12-29 18:18:22 -06:00
5cd3049d66 cdebug: added cosmoG_disassemble
for now cosmo will disassemble each script before running
2023-12-29 18:17:52 -06:00
cd37cfdae5 cparse: removed stale expressionStatement forward declare 2023-12-29 18:01:33 -06:00
e0455902b0 'return' is now a valid statement outside of a function
lets us do some cool things later. also the repl can print returned values. eg.

`return "hello world"` will print `<string> "hello world"` to the console
2023-12-28 23:41:10 -06:00
43d79a456e cparse.c: removed expressionStatement() 2023-12-28 23:27:08 -06:00
105a3d70c3 cparse.c: refactoring
- remove declaration(), replace calls with statement()
- fix possible UB in parsePrecedence; no idea how this *wasn't* causing a segfault tbh
2023-12-28 23:20:19 -06:00
93f3ae1106 cvm.c:cosmoV_printError -> cosmoV_printBacktrace 2023-12-28 22:56:57 -06:00
4816e64612 cvalue.c:printValue renamed to cosmoV_printValue 2023-12-28 22:52:20 -06:00
0df56bd42a ctable: hash COBJ_CFUNCTION based on cfunc and not the actual <obj> 2023-12-28 19:56:25 -06:00
14 changed files with 68 additions and 54 deletions

View File

@@ -1,7 +1,4 @@
# Cosmo
[![Check Build](https://github.com/CPunch/Cosmo/actions/workflows/check_build.yaml/badge.svg?branch=main)](https://github.com/CPunch/Cosmo/actions/workflows/check_build.yaml)
## Usage
```
Usage: ./bin/cosmo [-clsr] [args]
@@ -13,6 +10,13 @@ available options are:
-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'?
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
View File

@@ -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)
if (cosmoV_compileString(state, script, mod)) {
// 0 args being passed, 0 results expected
if (!cosmoV_pcall(state, 0, 0)) {
cosmoV_printError(state, cosmoV_readError(*cosmoV_pop(state)));
cosmoG_disassemble(cosmoV_readClosure(*cosmoV_getTop(state, 0)));
if (!cosmoV_pcall(state, 0, 1)) {
cosmoV_printBacktrace(state, cosmoV_readError(*cosmoV_pop(state)));
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 {
cosmoV_printError(state, cosmoV_readError(*cosmoV_pop(state)));
cosmoV_printBacktrace(state, cosmoV_readError(*cosmoV_pop(state)));
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;
cosmoD_dump(state, func, fileWriter, (void *)fout);
} else {
cosmoV_printError(state, cosmoV_readError(*cosmoV_pop(state)));
cosmoV_printBacktrace(state, cosmoV_readError(*cosmoV_pop(state)));
}
free(script);
@@ -171,13 +182,13 @@ void loadScript(CState *state, const char *in)
{
FILE *file = fopen(in, "rb");
if (!cosmoV_undump(state, fileReader, file)) {
cosmoV_printError(state, cosmoV_readError(*cosmoV_pop(state)));
cosmoV_printBacktrace(state, cosmoV_readError(*cosmoV_pop(state)));
return;
};
printf("[!] loaded %s!\n", in);
if (!cosmoV_pcall(state, 0, 0))
cosmoV_printError(state, cosmoV_readError(*cosmoV_pop(state)));
cosmoV_printBacktrace(state, cosmoV_readError(*cosmoV_pop(state)));
fclose(file);
}

View File

@@ -18,7 +18,7 @@ int cosmoB_print(CState *state, int nargs, CValue *args)
CObjString *str = cosmoV_toString(state, args[i]);
printf("%s", cosmoO_readCString(str));
} else { // else, thats pretty expensive for primitives, just print the raw value
printValue(args[i]);
cosmoV_printValue(args[i]);
}
}
printf("\n");

View File

@@ -62,7 +62,7 @@ static int constInstruction(const char *name, CChunk *chunk, int offset)
printf("%-16s [%05d] - ", name, index);
CValue val = chunk->constants.values[index];
printValue(val);
cosmoV_printValue(val);
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);
offset += 3; // we consumed the opcode + u16
printValue(val);
cosmoV_printValue(val);
printf("\n");
// list the upvalues/locals that are captured
@@ -223,3 +223,8 @@ int disasmInstr(CChunk *chunk, int offset, int indent)
return 1;
}
void cosmoG_disassemble(CObjClosure *closure)
{
disasmChunk(&closure->function->chunk, closure->function->name == NULL ? UNNAMEDCHUNK : closure->function->name->str, 0);
}

View File

@@ -2,10 +2,13 @@
#define CDEBUG_H
#include "cchunk.h"
#include "cobj.h"
COSMO_API void disasmChunk(CChunk *chunk, const char *name, int indent);
COSMO_API int disasmInstr(CChunk *chunk, int offset, int indent);
void printIndent(int indent);
COSMO_API void cosmoG_disassemble(CObjClosure *closure);
#endif

View File

@@ -715,13 +715,13 @@ void printObject(CObj *o)
case COBJ_ERROR: {
CObjError *err = (CObjError *)o;
printf("%p -> ", (void *)o);
printValue(err->err);
cosmoV_printValue(err->err);
break;
}
case COBJ_METHOD: {
CObjMethod *method = (CObjMethod *)o;
printf("%p -> ", (void *)method);
printValue(method->func);
cosmoV_printValue(method->func);
break;
}
case COBJ_CLOSURE: {
@@ -733,7 +733,7 @@ void printObject(CObj *o)
case COBJ_UPVALUE: {
CObjUpval *upval = (CObjUpval *)o;
printf("%p -> ", (void *)upval->val);
printValue(*upval->val);
cosmoV_printValue(*upval->val);
break;
}
default:

View File

@@ -55,7 +55,7 @@ struct CObjError
CCallFrame *frames;
int frameCount;
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

View File

@@ -102,9 +102,7 @@ static int expressionPrecedence(CParseState *pstate, int needed, Precedence prec
// returns # of pushed values onto the stack
static int expression(CParseState *pstate, int needed, bool forceNeeded);
static void statement(CParseState *pstate);
static void declaration(CParseState *pstate);
static void parseFunction(CParseState *pstate, FunctionType type);
static void expressionStatement(CParseState *pstate);
static ParseRule *getRule(CTokenType type);
static CObjFunction *endCompiler(CParseState *pstate);
@@ -1099,18 +1097,19 @@ static ParseRule *getRule(CTokenType type)
// returns true if it got past the first token (aka prefix wasn't null)
static bool parsePrecedence(CParseState *pstate, Precedence prec)
{
bool canAssign;
ParseFunc prefix, infix;
advance(pstate);
ParseFunc prefix = getRule(pstate->previous.type)->prefix;
if (prefix == NULL)
if ((prefix = getRule(pstate->previous.type)->prefix) == NULL)
return false;
bool canAssign = prec <= PREC_ASSIGNMENT;
canAssign = prec <= PREC_ASSIGNMENT;
prefix(pstate, canAssign, prec);
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);
infix(pstate, canAssign, prec);
}
@@ -1264,7 +1263,7 @@ static void endScope(CParseState *pstate)
static void block(CParseState *pstate)
{
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.'");
@@ -1321,7 +1320,7 @@ static void ifStatement(CParseState *pstate)
while (!check(pstate, TOKEN_END) && !check(pstate, TOKEN_ELSE) &&
!check(pstate, TOKEN_ELSEIF) && !check(pstate, TOKEN_EOF) &&
!check(pstate, TOKEN_ERROR)) {
declaration(pstate);
statement(pstate);
}
endScope(pstate);
@@ -1471,10 +1470,10 @@ static void functionDeclaration(CParseState *pstate)
static void returnStatement(CParseState *pstate)
{
if (pstate->compiler->type != FTYPE_FUNCTION && pstate->compiler->type != FTYPE_METHOD) {
error(pstate, "Expected 'return' in function!");
return;
}
// if (pstate->compiler->type != FTYPE_FUNCTION && pstate->compiler->type != FTYPE_METHOD) {
// error(pstate, "Expected 'return' in function!");
// return;
// }
if (blockFollow(pstate->current)) { // does this return have a value
writeu8(pstate, OP_NIL);
@@ -1589,7 +1588,7 @@ static void forLoop(CParseState *pstate)
// parse initializer
if (!match(pstate, TOKEN_EOS)) {
expressionStatement(pstate);
statement(pstate);
consume(pstate, TOKEN_EOS, "Expected ';' after initializer");
}
@@ -1705,7 +1704,7 @@ static int expression(CParseState *pstate, int needed, bool forceNeeded)
forceNeeded); // anything above assignments are an expression
}
static void expressionStatement(CParseState *pstate)
static void statement(CParseState *pstate)
{
int savedPushed = pstate->compiler->pushedValues;
@@ -1760,16 +1759,6 @@ static void expressionStatement(CParseState *pstate)
alignStack(pstate, savedPushed);
}
static void statement(CParseState *pstate)
{
expressionStatement(pstate);
}
static void declaration(CParseState *pstate)
{
statement(pstate);
}
static CObjFunction *endCompiler(CParseState *pstate)
{
popLocals(pstate, pstate->compiler->scopeDepth + 1); // remove the locals from other scopes
@@ -1794,7 +1783,7 @@ CObjFunction *cosmoP_compileString(CState *state, const char *source, const char
advance(&parser);
while (!match(&parser, TOKEN_EOF)) {
declaration(&parser);
statement(&parser);
}
consume(&parser, TOKEN_EOF, "End of file expected!");

View File

@@ -203,7 +203,7 @@ void cosmoV_printStack(CState *state)
printf("==== [[ stack dump ]] ====\n");
for (CValue *top = state->top - 1; top >= state->stack; top--) {
printf("%d: ", (int)(top - state->stack));
printValue(*top);
cosmoV_printValue(*top);
printf("\n");
}
}

View File

@@ -69,6 +69,8 @@ static uint32_t getObjectHash(CObj *obj)
switch (obj->type) {
case COBJ_STRING:
return ((CObjString *)obj)->hash;
case COBJ_CFUNCTION:
return (uint32_t)((CObjCFunction *)obj)->cfunc;
default:
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++) {
CTableEntry *entry = &tbl->table[i];
if (!(IS_NIL(entry->key))) {
printValue(entry->key);
cosmoV_printValue(entry->key);
printf(" - ");
printValue(entry->val);
cosmoV_printValue(entry->val);
printf("\n");
}
}

View File

@@ -101,7 +101,7 @@ const char *cosmoV_typeStr(CValue val)
}
}
void printValue(CValue val)
void cosmoV_printValue(CValue val)
{
switch (GET_TYPE(val)) {
case COSMO_TNUMBER:

View File

@@ -119,7 +119,7 @@ void initValArray(CState *state, CValueArray *val, size_t startCapacity);
void cleanValArray(CState *state, CValueArray *array); // cleans array
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 CObjString *cosmoV_toString(CState *state, CValue val);
COSMO_API cosmo_Number cosmoV_toNumber(CState *state, CValue val);

View File

@@ -78,7 +78,7 @@ bool cosmoV_compileString(CState *state, const char *src, const char *name)
return false;
}
void cosmoV_printError(CState *state, CObjError *err)
void cosmoV_printBacktrace(CState *state, CObjError *err)
{
// print stack trace
for (int i = 0; i < err->frameCount; i++) {
@@ -129,7 +129,7 @@ void cosmoV_throw(CState *state)
} else {
cosmoV_pushValue(state, val);
fprintf(stderr, "Unhandled panic! ");
cosmoV_printError(state, error);
cosmoV_printBacktrace(state, error);
exit(1);
}
}
@@ -340,7 +340,7 @@ void callCValue(CState *state, CValue func, int args, int nresults, int offset)
#ifdef VM_DEBUG
printf("\n");
printIndent(state->frameCount - 1);
printValue(func);
cosmoV_printValue(func);
printf("(%d args)\n", args);
#endif

View File

@@ -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_concat(CState *state, int vals);
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_error(CState *state, const char *format, ...);
COSMO_API void cosmoV_insert(CState *state, int indx, CValue val);