mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-21 15:00:06 +00:00
WIP: major error handling refactoring
switching to setjmp instead of the really bad global 'panic' flag
This commit is contained in:
parent
3f39211081
commit
75d27afe2c
@ -389,9 +389,8 @@ static CToken parseIdentifier(CLexState *state)
|
|||||||
return makeToken(state, identifierType(state)); // is it a reserved word?
|
return makeToken(state, identifierType(state)); // is it a reserved word?
|
||||||
}
|
}
|
||||||
|
|
||||||
CLexState *cosmoL_newLexState(CState *cstate, const char *source)
|
void cosmoL_initLexState(CState *cstate, CLexState *state, const char *source)
|
||||||
{
|
{
|
||||||
CLexState *state = cosmoM_xmalloc(cstate, sizeof(CLexState));
|
|
||||||
state->startChar = (char *)source;
|
state->startChar = (char *)source;
|
||||||
state->currentChar = (char *)source;
|
state->currentChar = (char *)source;
|
||||||
state->line = 1;
|
state->line = 1;
|
||||||
@ -400,13 +399,11 @@ CLexState *cosmoL_newLexState(CState *cstate, const char *source)
|
|||||||
state->cstate = cstate;
|
state->cstate = cstate;
|
||||||
|
|
||||||
resetBuffer(state);
|
resetBuffer(state);
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cosmoL_freeLexState(CState *state, CLexState *lstate)
|
void cosmoL_cleanupLexState(CState *state, CLexState *lstate)
|
||||||
{
|
{
|
||||||
cosmoM_free(state, CLexState, lstate);
|
// stubbed
|
||||||
}
|
}
|
||||||
|
|
||||||
CToken cosmoL_scanToken(CLexState *state)
|
CToken cosmoL_scanToken(CLexState *state)
|
||||||
|
@ -103,8 +103,8 @@ typedef struct
|
|||||||
CState *cstate;
|
CState *cstate;
|
||||||
} CLexState;
|
} CLexState;
|
||||||
|
|
||||||
CLexState *cosmoL_newLexState(CState *state, const char *source);
|
void cosmoL_initLexState(CState *cstate, CLexState *state, const char *source);
|
||||||
void cosmoL_freeLexState(CState *state, CLexState *lstate);
|
void cosmoL_cleanupLexState(CState *state, CLexState *lstate);
|
||||||
|
|
||||||
CToken cosmoL_scanToken(CLexState *state);
|
CToken cosmoL_scanToken(CLexState *state);
|
||||||
|
|
||||||
|
73
src/cparse.c
73
src/cparse.c
@ -59,14 +59,12 @@ typedef struct CCompilerState
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
CLexState lex;
|
||||||
CState *state;
|
CState *state;
|
||||||
CLexState *lex;
|
|
||||||
CCompilerState *compiler;
|
CCompilerState *compiler;
|
||||||
CObjString *module; // name of the module
|
CObjString *module; // name of the module
|
||||||
CToken current;
|
CToken current;
|
||||||
CToken previous; // token right after the current token
|
CToken previous; // token right after the current token
|
||||||
bool hadError;
|
|
||||||
bool panic;
|
|
||||||
} CParseState;
|
} CParseState;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
@ -124,6 +122,8 @@ static void initCompilerState(CParseState *pstate, CCompilerState *ccstate, Func
|
|||||||
ccstate->function = cosmoO_newFunction(pstate->state);
|
ccstate->function = cosmoO_newFunction(pstate->state);
|
||||||
ccstate->function->module = pstate->module;
|
ccstate->function->module = pstate->module;
|
||||||
|
|
||||||
|
cosmoV_pushRef(pstate->state, (CObj *)ccstate->function);
|
||||||
|
|
||||||
ccstate->loop.scope = -1; // there is no loop yet
|
ccstate->loop.scope = -1; // there is no loop yet
|
||||||
|
|
||||||
if (type != FTYPE_SCRIPT) {
|
if (type != FTYPE_SCRIPT) {
|
||||||
@ -146,11 +146,9 @@ static void initCompilerState(CParseState *pstate, CCompilerState *ccstate, Func
|
|||||||
static void initParseState(CParseState *pstate, CCompilerState *ccstate, CState *s,
|
static void initParseState(CParseState *pstate, CCompilerState *ccstate, CState *s,
|
||||||
const char *source, const char *module)
|
const char *source, const char *module)
|
||||||
{
|
{
|
||||||
pstate->lex = cosmoL_newLexState(s, source);
|
cosmoL_initLexState(s, &pstate->lex, source);
|
||||||
|
|
||||||
pstate->state = s;
|
pstate->state = s;
|
||||||
pstate->hadError = false;
|
|
||||||
pstate->panic = false;
|
|
||||||
pstate->compiler = ccstate;
|
pstate->compiler = ccstate;
|
||||||
pstate->module = cosmoO_copyString(s, module, strlen(module));
|
pstate->module = cosmoO_copyString(s, module, strlen(module));
|
||||||
|
|
||||||
@ -159,14 +157,11 @@ static void initParseState(CParseState *pstate, CCompilerState *ccstate, CState
|
|||||||
|
|
||||||
static void freeParseState(CParseState *pstate)
|
static void freeParseState(CParseState *pstate)
|
||||||
{
|
{
|
||||||
cosmoL_freeLexState(pstate->state, pstate->lex);
|
cosmoL_cleanupLexState(pstate->state, &pstate->lex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void errorAt(CParseState *pstate, CToken *token, const char *format, va_list args)
|
static void errorAt(CParseState *pstate, CToken *token, const char *format, va_list args)
|
||||||
{
|
{
|
||||||
if (pstate->hadError)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (token->type == TOKEN_EOF) {
|
if (token->type == TOKEN_EOF) {
|
||||||
cosmoV_pushString(pstate->state, "At end: ");
|
cosmoV_pushString(pstate->state, "At end: ");
|
||||||
} else if (!(token->type == TOKEN_ERROR)) {
|
} else if (!(token->type == TOKEN_ERROR)) {
|
||||||
@ -177,14 +172,9 @@ static void errorAt(CParseState *pstate, CToken *token, const char *format, va_l
|
|||||||
|
|
||||||
cosmoO_pushVFString(pstate->state, format, args);
|
cosmoO_pushVFString(pstate->state, format, args);
|
||||||
|
|
||||||
cosmoV_concat(pstate->state, 2); // concats the two strings together
|
// throw complete error string
|
||||||
|
cosmoV_concat(pstate->state, 2);
|
||||||
CObjError *err = cosmoV_throw(pstate->state);
|
cosmoV_throw(pstate->state);
|
||||||
err->line = token->line;
|
|
||||||
err->parserError = true;
|
|
||||||
|
|
||||||
pstate->hadError = true;
|
|
||||||
pstate->panic = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void errorAtCurrent(CParseState *pstate, const char *format, ...)
|
static void errorAtCurrent(CParseState *pstate, const char *format, ...)
|
||||||
@ -206,7 +196,7 @@ static void error(CParseState *pstate, const char *format, ...)
|
|||||||
static void advance(CParseState *pstate)
|
static void advance(CParseState *pstate)
|
||||||
{
|
{
|
||||||
pstate->previous = pstate->current;
|
pstate->previous = pstate->current;
|
||||||
pstate->current = cosmoL_scanToken(pstate->lex);
|
pstate->current = cosmoL_scanToken(&pstate->lex);
|
||||||
|
|
||||||
if (pstate->current.type == TOKEN_ERROR) {
|
if (pstate->current.type == TOKEN_ERROR) {
|
||||||
errorAtCurrent(pstate, pstate->current.start);
|
errorAtCurrent(pstate, pstate->current.start);
|
||||||
@ -280,7 +270,6 @@ uint16_t makeConstant(CParseState *pstate, CValue val)
|
|||||||
int indx = addConstant(pstate->state, getChunk(pstate), val);
|
int indx = addConstant(pstate->state, getChunk(pstate), val);
|
||||||
if (indx > UINT16_MAX) {
|
if (indx > UINT16_MAX) {
|
||||||
error(pstate, "UInt overflow! Too many constants in one chunk!");
|
error(pstate, "UInt overflow! Too many constants in one chunk!");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (uint16_t)indx;
|
return (uint16_t)indx;
|
||||||
@ -350,7 +339,6 @@ static void addLocal(CParseState *pstate, CToken name)
|
|||||||
{
|
{
|
||||||
if (pstate->compiler->localCount > UINT8_MAX) {
|
if (pstate->compiler->localCount > UINT8_MAX) {
|
||||||
error(pstate, "UInt overflow! Too many locals in scope!");
|
error(pstate, "UInt overflow! Too many locals in scope!");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Local *local = &pstate->compiler->locals[pstate->compiler->localCount++];
|
Local *local = &pstate->compiler->locals[pstate->compiler->localCount++];
|
||||||
@ -365,7 +353,6 @@ static int addUpvalue(CParseState *pstate, CCompilerState *ccstate, uint8_t indx
|
|||||||
|
|
||||||
if (upvals > UINT8_MAX) {
|
if (upvals > UINT8_MAX) {
|
||||||
error(pstate, "UInt overflow! Too many upvalues in scope!");
|
error(pstate, "UInt overflow! Too many upvalues in scope!");
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check and make sure we haven't already captured it
|
// check and make sure we haven't already captured it
|
||||||
@ -768,7 +755,6 @@ static void table(CParseState *pstate, bool canAssign, Precedence prec)
|
|||||||
tblType = 1; // array-like
|
tblType = 1; // array-like
|
||||||
} else {
|
} else {
|
||||||
error(pstate, "Can't change table description type mid-definition!");
|
error(pstate, "Can't change table description type mid-definition!");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entries++;
|
entries++;
|
||||||
@ -818,7 +804,7 @@ static void object(CParseState *pstate, bool canAssign, Precedence prec)
|
|||||||
// "pop" the 1 value
|
// "pop" the 1 value
|
||||||
valuePopped(pstate, 1);
|
valuePopped(pstate, 1);
|
||||||
entries++;
|
entries++;
|
||||||
} while (match(pstate, TOKEN_COMMA) && !pstate->hadError);
|
} while (match(pstate, TOKEN_COMMA));
|
||||||
|
|
||||||
consume(pstate, TOKEN_RIGHT_BRACE, "Expected '}' to end object definition.");
|
consume(pstate, TOKEN_RIGHT_BRACE, "Expected '}' to end object definition.");
|
||||||
}
|
}
|
||||||
@ -1158,9 +1144,6 @@ static uint16_t parseVariable(CParseState *pstate, const char *errorMessage, boo
|
|||||||
|
|
||||||
static void defineVariable(CParseState *pstate, uint16_t global, bool forceLocal)
|
static void defineVariable(CParseState *pstate, uint16_t global, bool forceLocal)
|
||||||
{
|
{
|
||||||
if (pstate->hadError)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (pstate->compiler->scopeDepth > 0 || forceLocal) {
|
if (pstate->compiler->scopeDepth > 0 || forceLocal) {
|
||||||
markInitialized(pstate, global);
|
markInitialized(pstate, global);
|
||||||
valuePopped(pstate, 1); // the local stays on the stack!
|
valuePopped(pstate, 1); // the local stays on the stack!
|
||||||
@ -1177,7 +1160,7 @@ static void _proto(CParseState *pstate)
|
|||||||
{
|
{
|
||||||
int entries = 0;
|
int entries = 0;
|
||||||
|
|
||||||
while (!match(pstate, TOKEN_END) && !match(pstate, TOKEN_EOF) && !pstate->hadError) {
|
while (!match(pstate, TOKEN_END) && !match(pstate, TOKEN_EOF)) {
|
||||||
if (match(pstate, TOKEN_FUNC)) {
|
if (match(pstate, TOKEN_FUNC)) {
|
||||||
// define method
|
// define method
|
||||||
consume(pstate, TOKEN_IDENTIFIER, "Expected identifier for method!");
|
consume(pstate, TOKEN_IDENTIFIER, "Expected identifier for method!");
|
||||||
@ -1224,9 +1207,6 @@ static void localProto(CParseState *pstate)
|
|||||||
|
|
||||||
static void popLocals(CParseState *pstate, int toScope)
|
static void popLocals(CParseState *pstate, int toScope)
|
||||||
{
|
{
|
||||||
if (pstate->hadError)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// count the locals in scope to pop
|
// count the locals in scope to pop
|
||||||
int localsToPop = 0;
|
int localsToPop = 0;
|
||||||
|
|
||||||
@ -1686,18 +1666,6 @@ static void continueStatement(CParseState *pstate)
|
|||||||
writeJmpBack(pstate, pstate->compiler->loop.startBytecode);
|
writeJmpBack(pstate, pstate->compiler->loop.startBytecode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void synchronize(CParseState *pstate)
|
|
||||||
{
|
|
||||||
pstate->panic = false;
|
|
||||||
|
|
||||||
while (pstate->current.type != TOKEN_EOF) {
|
|
||||||
if (pstate->previous.type == TOKEN_EOS)
|
|
||||||
return;
|
|
||||||
|
|
||||||
advance(pstate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int expressionPrecedence(CParseState *pstate, int needed, Precedence prec, bool forceNeeded)
|
static int expressionPrecedence(CParseState *pstate, int needed, Precedence prec, bool forceNeeded)
|
||||||
{
|
{
|
||||||
int lastExpected = pstate->compiler->expectedValues;
|
int lastExpected = pstate->compiler->expectedValues;
|
||||||
@ -1787,10 +1755,6 @@ static void statement(CParseState *pstate)
|
|||||||
static void declaration(CParseState *pstate)
|
static void declaration(CParseState *pstate)
|
||||||
{
|
{
|
||||||
statement(pstate);
|
statement(pstate);
|
||||||
|
|
||||||
// if we paniced, skip the whole statement!
|
|
||||||
if (pstate->panic)
|
|
||||||
synchronize(pstate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static CObjFunction *endCompiler(CParseState *pstate)
|
static CObjFunction *endCompiler(CParseState *pstate)
|
||||||
@ -1812,7 +1776,6 @@ CObjFunction *cosmoP_compileString(CState *state, const char *source, const char
|
|||||||
{
|
{
|
||||||
CParseState parser;
|
CParseState parser;
|
||||||
CCompilerState compiler;
|
CCompilerState compiler;
|
||||||
cosmoM_freezeGC(state); // ignore all GC events while compiling
|
|
||||||
initParseState(&parser, &compiler, state, source, module);
|
initParseState(&parser, &compiler, state, source, module);
|
||||||
|
|
||||||
advance(&parser);
|
advance(&parser);
|
||||||
@ -1825,24 +1788,10 @@ CObjFunction *cosmoP_compileString(CState *state, const char *source, const char
|
|||||||
|
|
||||||
popLocals(&parser, 0);
|
popLocals(&parser, 0);
|
||||||
|
|
||||||
if (parser.hadError) { // we don't free the function, the state already has a reference to it in
|
|
||||||
// it's linked list of objects!
|
|
||||||
endCompiler(&parser);
|
|
||||||
freeParseState(&parser);
|
|
||||||
|
|
||||||
cosmoM_unfreezeGC(state);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CObjFunction *resFunc = compiler.function;
|
CObjFunction *resFunc = compiler.function;
|
||||||
|
|
||||||
// finally free out parser states
|
// finally free out parser states
|
||||||
endCompiler(&parser);
|
endCompiler(&parser);
|
||||||
freeParseState(&parser);
|
freeParseState(&parser);
|
||||||
|
|
||||||
// push the funciton onto the stack so if we cause an GC event, it won't be free'd
|
|
||||||
cosmoV_pushRef(state, (CObj *)resFunc);
|
|
||||||
cosmoM_unfreezeGC(state);
|
|
||||||
cosmoV_pop(state);
|
|
||||||
return resFunc;
|
return resFunc;
|
||||||
}
|
}
|
||||||
|
16
src/cstate.c
16
src/cstate.c
@ -7,6 +7,21 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
CPanic *cosmoV_newPanic(CState *state)
|
||||||
|
{
|
||||||
|
CPanic *panic = cosmoM_xmalloc(state, sizeof(CPanic));
|
||||||
|
panic->prev = state->panic;
|
||||||
|
state->panic = panic;
|
||||||
|
return panic;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cosmoV_freePanic(CState *state)
|
||||||
|
{
|
||||||
|
CPanic *panic = state->panic;
|
||||||
|
state->panic = panic->prev;
|
||||||
|
cosmoM_free(state, CPanic, panic);
|
||||||
|
}
|
||||||
|
|
||||||
CState *cosmoV_newState()
|
CState *cosmoV_newState()
|
||||||
{
|
{
|
||||||
// we use C's malloc because we don't want to trigger a GC with an invalid state
|
// we use C's malloc because we don't want to trigger a GC with an invalid state
|
||||||
@ -19,6 +34,7 @@ CState *cosmoV_newState()
|
|||||||
|
|
||||||
state->panic = false;
|
state->panic = false;
|
||||||
state->freezeGC = 1; // we start frozen
|
state->freezeGC = 1; // we start frozen
|
||||||
|
state->panic = NULL;
|
||||||
|
|
||||||
// GC
|
// GC
|
||||||
state->objects = NULL;
|
state->objects = NULL;
|
||||||
|
17
src/cstate.h
17
src/cstate.h
@ -6,6 +6,8 @@
|
|||||||
#include "ctable.h"
|
#include "ctable.h"
|
||||||
#include "cvalue.h"
|
#include "cvalue.h"
|
||||||
|
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
struct CCallFrame
|
struct CCallFrame
|
||||||
{
|
{
|
||||||
CObjClosure *closure;
|
CObjClosure *closure;
|
||||||
@ -38,11 +40,17 @@ typedef struct ArrayCObj
|
|||||||
int capacity;
|
int capacity;
|
||||||
} ArrayCObj;
|
} ArrayCObj;
|
||||||
|
|
||||||
|
typedef struct CPanic
|
||||||
|
{
|
||||||
|
jmp_buf jmp;
|
||||||
|
struct CPanic *prev;
|
||||||
|
} CPanic;
|
||||||
|
|
||||||
struct CState
|
struct CState
|
||||||
{
|
{
|
||||||
bool panic;
|
|
||||||
int freezeGC; // when > 0, GC events will be ignored (for internal use)
|
int freezeGC; // when > 0, GC events will be ignored (for internal use)
|
||||||
int frameCount;
|
int frameCount;
|
||||||
|
CPanic *panic;
|
||||||
|
|
||||||
CObjError *error; // NULL, unless panic is true
|
CObjError *error; // NULL, unless panic is true
|
||||||
CObj *objects; // tracks all of our allocated objects
|
CObj *objects; // tracks all of our allocated objects
|
||||||
@ -64,10 +72,15 @@ struct CState
|
|||||||
CValue stack[STACK_MAX]; // stack
|
CValue stack[STACK_MAX]; // stack
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CPanic *cosmoV_newPanic(CState *state);
|
||||||
|
void cosmoV_freePanic(CState *state);
|
||||||
|
|
||||||
COSMO_API CState *cosmoV_newState();
|
COSMO_API CState *cosmoV_newState();
|
||||||
|
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_register(CState *state, int pairs);
|
||||||
COSMO_API void cosmoV_freeState(CState *state);
|
|
||||||
COSMO_API void cosmoV_printStack(CState *state);
|
COSMO_API void cosmoV_printStack(CState *state);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
69
src/cvm.c
69
src/cvm.c
@ -10,6 +10,18 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
bool cosmoV_protect(CState *state)
|
||||||
|
{
|
||||||
|
CPanic *panic = cosmoV_newPanic(state);
|
||||||
|
|
||||||
|
if (setjmp(panic->jmp) == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cosmoV_freePanic(state);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...)
|
COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
@ -57,21 +69,20 @@ COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *
|
|||||||
{
|
{
|
||||||
CObjFunction *func;
|
CObjFunction *func;
|
||||||
|
|
||||||
if ((func = cosmoP_compileString(state, src, name)) != NULL) {
|
if (cosmoV_protect(state)) {
|
||||||
// success
|
if ((func = cosmoP_compileString(state, src, name)) != NULL) {
|
||||||
|
// success
|
||||||
#ifdef VM_DEBUG
|
#ifdef VM_DEBUG
|
||||||
disasmChunk(&func->chunk, func->module->str, 0);
|
disasmChunk(&func->chunk, func->module->str, 0);
|
||||||
#endif
|
#endif
|
||||||
// push function onto the stack so it doesn't it cleaned up by the GC, at the same stack
|
// push function onto the stack so it doesn't it cleaned up by the GC, at the same stack
|
||||||
// location put our closure
|
// location put our closure
|
||||||
cosmoV_pushRef(state, (CObj *)func);
|
cosmoV_pushRef(state, (CObj *)func);
|
||||||
*(cosmoV_getTop(state, 0)) = cosmoV_newRef(cosmoO_newClosure(state, func));
|
*(cosmoV_getTop(state, 0)) = cosmoV_newRef(cosmoO_newClosure(state, func));
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fail recovery
|
|
||||||
state->panic = false;
|
|
||||||
cosmoV_pushRef(state, (CObj *)state->error);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,30 +120,26 @@ COSMO_API void cosmoV_printError(CState *state, CObjError *err)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
takes value on top of the stack and wraps an CObjError around it, state->error is set to that
|
takes value on top of the stack and wraps an CObjError around it, then throws it
|
||||||
value the value on the stack is *expected* to be a string, but not required, so yes, this means
|
|
||||||
you could throw a nil value if you really wanted too..
|
|
||||||
*/
|
*/
|
||||||
CObjError *cosmoV_throw(CState *state)
|
void cosmoV_throw(CState *state)
|
||||||
{
|
{
|
||||||
StkPtr temp = cosmoV_getTop(state, 0);
|
StkPtr temp = cosmoV_getTop(state, 0);
|
||||||
|
|
||||||
CObjError *error = cosmoO_newError(state, *temp);
|
CObjError *error = cosmoO_newError(state, *temp);
|
||||||
state->error = error;
|
|
||||||
state->panic = true;
|
|
||||||
|
|
||||||
cosmoV_pop(state); // pops thrown value off the stack
|
// replace the value on the stack with the error
|
||||||
return error;
|
*temp = cosmoV_newRef((CObj *)cosmoO_newError(state, *temp));
|
||||||
|
if (state->panic) {
|
||||||
|
longjmp(state->panic->jmp, 1);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unhandled panic! ");
|
||||||
|
cosmoV_printError(state, error);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cosmoV_error(CState *state, const char *format, ...)
|
void cosmoV_error(CState *state, const char *format, ...)
|
||||||
{
|
{
|
||||||
if (state->panic)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// i set panic before calling cosmoO_pushVFString, since that can also call cosmoV_error
|
|
||||||
state->panic = true;
|
|
||||||
|
|
||||||
// format the error string and push it onto the stack
|
// format the error string and push it onto the stack
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
@ -422,9 +429,11 @@ bool invokeMethod(CState *state, CObj *obj, CValue func, int args, int nresults,
|
|||||||
// returns false if function call failed, true if function call succeeded
|
// returns false if function call failed, true if function call succeeded
|
||||||
bool cosmoV_pcall(CState *state, int args, int nresults)
|
bool cosmoV_pcall(CState *state, int args, int nresults)
|
||||||
{
|
{
|
||||||
StkPtr base = cosmoV_getTop(state, args);
|
if (cosmoV_protect(state)) {
|
||||||
|
cosmoV_call(state, args, nresults);
|
||||||
if (!callCValue(state, *base, args, nresults, 0)) {
|
return true;
|
||||||
|
} else {
|
||||||
|
printf("caught panic!\n");
|
||||||
// restore panic state
|
// restore panic state
|
||||||
state->panic = false;
|
state->panic = false;
|
||||||
|
|
||||||
@ -438,8 +447,6 @@ bool cosmoV_pcall(CState *state, int args, int nresults)
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// calls a callable object at stack->top - args - 1, passing the # of args to the callable, and
|
// calls a callable object at stack->top - args - 1, passing the # of args to the callable, and
|
||||||
|
@ -31,7 +31,7 @@ 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_printError(CState *state, CObjError *err);
|
||||||
COSMO_API CObjError *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 cosmo_insert(CState *state, int indx, CValue val);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user