Compare commits

..

6 Commits

Author SHA1 Message Date
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
12 changed files with 52 additions and 50 deletions

24
main.c
View File

@ -50,13 +50,23 @@ 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 if (!cosmoV_pcall(state, 0, 1)) {
if (!cosmoV_pcall(state, 0, 0)) { cosmoV_printBacktrace(state, cosmoV_readError(*cosmoV_pop(state)));
cosmoV_printError(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 +168,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 +181,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);
} }

View 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");

View File

@ -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

View File

@ -715,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: {
@ -733,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:

View File

@ -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

View File

@ -102,7 +102,6 @@ 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 void expressionStatement(CParseState *pstate);
static ParseRule *getRule(CTokenType type); static ParseRule *getRule(CTokenType type);
@ -1099,18 +1098,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);
} }
@ -1264,7 +1264,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.'");
@ -1321,7 +1321,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);
@ -1471,10 +1471,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);
@ -1589,7 +1589,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");
} }
@ -1705,7 +1705,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;
@ -1760,16 +1760,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
@ -1794,7 +1784,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!");

View File

@ -203,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");
} }
} }

View File

@ -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");
} }
} }

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)) { switch (GET_TYPE(val)) {
case COSMO_TNUMBER: 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 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);

View File

@ -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

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_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);