📄 compiler.cpp
字号:
compiler->compileBlock(stmt);
CtkSymbol* symbols = compiler->currCtx->symbols;
symIdx = compiler->currCtx->nSymbols++;
CtkSymbol sym(param, symIdx, symbols);
compiler->currCtx->symbols = &sym;
compiler->compileBlock(handler);
compiler->currCtx->symbols = symbols;
}
JumpType CtkTryStmt::execute(CtkFrame* frame)
{
CtkThread* currThread = frame->thread;
int sp = currThread->sp;
CtkFrame* saveTrace = currThread->exceptionTrace;
#ifdef USE_CTALK_EXCEPTION
try {
#else
jmp_buf buf;
jmp_buf* saveBuf = currThread->catchCtx;
currThread->catchCtx = &buf;
if (setjmp(buf) == 0) {
#endif
JumpType jump = stmt->executeBlock(frame);
#ifndef USE_CTALK_EXCEPTION
currThread->catchCtx = saveBuf;
#endif
currThread->sp = sp;
switch (jump) {
case JMP_EXCEPTION:
currThread->exceptionTrace = frame->up;
frame->up = NULL;
frame->vars[symIdx] = currThread->exceptionObject;
jump = handler->executeBlock(frame);
currThread->exceptionTrace = saveTrace;
return jump;
case JMP_NEXT:
return JMP_NEXT;
default:
return jump;
}
#ifdef USE_CTALK_EXCEPTION
} catch (CtkException const& x) {
#else
} else {
currThread->catchCtx = saveBuf;
#endif
frame->vars[symIdx] = currThread->exceptionObject;
currThread->exceptionTrace = frame->up;
frame->up = NULL;
currThread->sp = sp;
JumpType jump = handler->executeBlock(frame);
currThread->exceptionTrace = saveTrace;
return jump;
}
}
void CtkExprStmt::compile(CtkCompiler* compiler)
{
expr->compile(compiler);
}
JumpType CtkExprStmt::execute(CtkFrame* frame)
{
expr->getRvalue(frame);
POP(frame->thread);
return JMP_NEXT;
}
void CtkSynchronizedStmt::compile(CtkCompiler* compiler)
{
mutex->compile(compiler);
compiler->compileBlock(stmt);
}
JumpType CtkSynchronizedStmt::execute(CtkFrame* frame)
{
CtkObject cs = mutex->getRvalue(frame);
if (cs.type != CTK_MUTEX) {
THROW_EXCEPTION("synchronized parameter should be mutex");
}
#ifdef USE_CTALK_EXCEPTION
CtkCriticalSection lock((CtkMutex*)cs.u.ptr);
return stmt->executeBlock(frame);
#else
ctkLockMutex((CtkMutex*)cs.u.ptr);
CtkThread* currThread = frame->thread;
jmp_buf buf;
jmp_buf* saveCtx = currThread->catchCtx;
currThread->catchCtx = &buf;
JumpType jump;
if (setjmp(buf) == 0) {
jump = stmt->executeBlock(frame);
ctkUnlockMutex((CtkMutex*)cs.u.ptr);
POP(currThread);
currThread->catchCtx = saveCtx;
} else {
jump = stmt->executeBlock(frame);
ctkUnlockMutex((CtkMutex*)cs.u.ptr);
POP(currThread);
currThread->catchCtx = saveCtx;
longjmp(*saveCtx, 1);
}
return jump;
#endif
}
void CtkBinaryExpr::compile(CtkCompiler* compiler, CompileCtx)
{
left->compile(compiler);
right->compile(compiler);
}
CtkObject CtkAddExpr::getRvalue(CtkFrame* frame)
{
CtkObject lvalue = left->getRvalue(frame);
CtkObject rvalue = right->getRvalue(frame);
CtkObject result;
if (lvalue.type == CTK_ARRAY && rvalue.type == CTK_ARRAY) {
CtkMemoryManager::instance.beginAccess(frame->thread);
CtkArray* arr = ctkCloneArray((CtkArray*)lvalue.u.ptr);
ctkAddArray(arr, (CtkArray*)rvalue.u.ptr);
MAKE_ARRAY(result, arr);
POP2(frame->thread);
PUSH(frame->thread, result);
CtkMemoryManager::instance.endAccess(frame->thread);
return result;
} else if (lvalue.type == CTK_STRING || rvalue.type == CTK_STRING) {
char buf[64];
if (lvalue.type == CTK_INTEGER) {
sprintf(buf, "%ld", (long)lvalue.u.ivalue);
lvalue.u.svalue = buf;
} else if (lvalue.type == CTK_REAL) {
sprintf(buf, "%f", lvalue.u.rvalue);
lvalue.u.svalue = buf;
} else if (lvalue.type != CTK_STRING) {
THROW_EXCEPTION("Invalid left operand for + operator");
}
if (rvalue.type == CTK_INTEGER) {
sprintf(buf, "%ld", (long)rvalue.u.ivalue);
rvalue.u.svalue = buf;
} else if (rvalue.type == CTK_REAL) {
sprintf(buf, "%f", rvalue.u.rvalue);
rvalue.u.svalue = buf;
} else if (rvalue.type != CTK_STRING) {
THROW_EXCEPTION("Invalid right operand for + operator");
}
int headLen = strlen(lvalue.u.svalue);
int tailLen = strlen(rvalue.u.svalue);
CtkMemoryManager::instance.beginAccess(frame->thread);
char* p = (char*)ctkAllocateObject(headLen + tailLen + 1, NULL);
memcpy(p, lvalue.u.svalue, headLen);
memcpy(p + headLen, rvalue.u.svalue, tailLen+1);
MAKE_STRING(result, p);
POP2(frame->thread);
PUSH(frame->thread, result);
CtkMemoryManager::instance.endAccess(frame->thread);
return result;
} else if (lvalue.type == CTK_REAL && rvalue.type == CTK_REAL) {
POP(frame->thread);
TOP(frame->thread).u.rvalue = lvalue.u.rvalue += rvalue.u.rvalue;
} else if (lvalue.type == CTK_REAL && rvalue.type == CTK_INTEGER) {
POP(frame->thread);
TOP(frame->thread).u.rvalue = lvalue.u.rvalue += rvalue.u.ivalue;
} else if (rvalue.type == CTK_REAL && lvalue.type == CTK_INTEGER) {
POP(frame->thread);
lvalue.u.rvalue = lvalue.u.ivalue + rvalue.u.rvalue;
lvalue.type = CTK_REAL;
TOP(frame->thread).u.rvalue = lvalue.u.rvalue;
} else if (lvalue.type == CTK_INTEGER && rvalue.type == CTK_INTEGER) {
POP(frame->thread);
TOP(frame->thread).u.ivalue = lvalue.u.ivalue += rvalue.u.ivalue;
} else {
THROW_EXCEPTION("Bad operands for + operator");
}
return lvalue;
}
CtkObject CtkSubExpr::getRvalue(CtkFrame* frame)
{
CtkObject lvalue = left->getRvalue(frame);
CtkObject rvalue = right->getRvalue(frame);
if (lvalue.type == CTK_ARRAY) {
CtkMemoryManager::instance.beginAccess(frame->thread);
CtkArray* arr = ctkCloneArray((CtkArray*)lvalue.u.ptr);
if (rvalue.type == CTK_ARRAY) {
ctkSubArray(arr, (CtkArray*)rvalue.u.ptr);
} else {
ctkDelArray(arr, rvalue);
}
CtkObject result;
MAKE_ARRAY(result, arr);
POP2(frame->thread);
PUSH(frame->thread, result);
CtkMemoryManager::instance.endAccess(frame->thread);
return result;
}
if (lvalue.type == CTK_REAL && rvalue.type == CTK_REAL) {
POP(frame->thread);
TOP(frame->thread).u.rvalue = lvalue.u.rvalue -= rvalue.u.rvalue;
} else if (lvalue.type == CTK_REAL && rvalue.type == CTK_INTEGER) {
POP(frame->thread);
TOP(frame->thread).u.rvalue = lvalue.u.rvalue -= rvalue.u.ivalue;
} else if (rvalue.type == CTK_REAL && lvalue.type == CTK_INTEGER) {
POP(frame->thread);
lvalue.u.rvalue = lvalue.u.ivalue - rvalue.u.rvalue;
lvalue.type = CTK_REAL;
TOP(frame->thread).u.rvalue = lvalue.u.rvalue;
} else if (lvalue.type == CTK_INTEGER && rvalue.type == CTK_INTEGER) {
POP(frame->thread);
TOP(frame->thread).u.ivalue = lvalue.u.ivalue -= rvalue.u.ivalue;
} else {
THROW_EXCEPTION("Bad operands for - operator");
}
return lvalue;
}
CtkObject CtkMulExpr::getRvalue(CtkFrame* frame)
{
CtkObject lvalue = left->getRvalue(frame);
CtkObject rvalue = right->getRvalue(frame);
if (lvalue.type == CTK_REAL && rvalue.type == CTK_REAL) {
POP(frame->thread);
TOP(frame->thread).u.rvalue = lvalue.u.rvalue *= rvalue.u.rvalue;
} else if (lvalue.type == CTK_REAL && rvalue.type == CTK_INTEGER) {
POP(frame->thread);
TOP(frame->thread).u.rvalue = lvalue.u.rvalue *= rvalue.u.ivalue;
} else if (rvalue.type == CTK_REAL && lvalue.type == CTK_INTEGER) {
POP(frame->thread);
lvalue.u.rvalue = lvalue.u.ivalue * rvalue.u.rvalue;
lvalue.type = CTK_REAL;
TOP(frame->thread).u.rvalue = lvalue.u.rvalue;
} else if (lvalue.type == CTK_INTEGER && rvalue.type == CTK_INTEGER) {
POP(frame->thread);
TOP(frame->thread).u.ivalue = lvalue.u.ivalue *= rvalue.u.ivalue;
} else {
THROW_EXCEPTION("Bad operands for * operator");
}
return lvalue;
}
CtkObject CtkDivExpr::getRvalue(CtkFrame* frame)
{
CtkObject lvalue = left->getRvalue(frame);
CtkObject rvalue = right->getRvalue(frame);
if (rvalue.type == CTK_INTEGER) {
if (rvalue.u.ivalue == 0) {
THROW_EXCEPTION("Divided by zero");
}
} else if (rvalue.type == CTK_REAL) {
if (rvalue.u.rvalue == 0.0) {
THROW_EXCEPTION("Divided by zero");
}
}
if (lvalue.type == CTK_REAL && rvalue.type == CTK_REAL) {
POP(frame->thread);
TOP(frame->thread).u.rvalue = lvalue.u.rvalue /= rvalue.u.rvalue;
} else if (lvalue.type == CTK_REAL && rvalue.type == CTK_INTEGER) {
POP(frame->thread);
TOP(frame->thread).u.rvalue = lvalue.u.rvalue /= rvalue.u.ivalue;
} else if (rvalue.type == CTK_REAL && lvalue.type == CTK_INTEGER) {
POP(frame->thread);
lvalue.u.rvalue = lvalue.u.ivalue / rvalue.u.rvalue;
lvalue.type = CTK_REAL;
TOP(frame->thread).u.rvalue = lvalue.u.rvalue;
} else if (lvalue.type == CTK_INTEGER && rvalue.type == CTK_INTEGER) {
POP(frame->thread);
TOP(frame->thread).u.ivalue = lvalue.u.ivalue /= rvalue.u.ivalue;
} else {
THROW_EXCEPTION("Bad operands for / operator");
}
return lvalue;
}
CtkObject CtkModExpr::getRvalue(CtkFrame* frame)
{
CtkObject lvalue = left->getRvalue(frame);
CtkObject rvalue = right->getRvalue(frame);
if (rvalue.type == CTK_INTEGER) {
if (rvalue.u.ivalue == 0) {
THROW_EXCEPTION("Divided by zero");
}
} else if (rvalue.type == CTK_REAL) {
if (rvalue.u.rvalue == 0.0) {
THROW_EXCEPTION("Divided by zero");
}
}
if (lvalue.type == CTK_INTEGER && rvalue.type == CTK_INTEGER) {
POP(frame->thread);
TOP(frame->thread).u.ivalue = lvalue.u.ivalue %= rvalue.u.ivalue;
} else {
THROW_EXCEPTION("Bad operands for % operator");
}
return lvalue;
}
CtkObject CtkOrExpr::getRvalue(CtkFrame* frame)
{
CtkObject lvalue = left->getRvalue(frame);
CtkObject rvalue = right->getRvalue(frame);
if (lvalue.type == CTK_INTEGER && rvalue.type == CTK_INTEGER) {
POP(frame->thread);
TOP(frame->thread).u.ivalue = lvalue.u.ivalue |= rvalue.u.ivalue;
} else {
THROW_EXCEPTION("Bad operands for | operator");
}
return lvalue;
}
CtkObject CtkAndExpr::getRvalue(CtkFrame* frame)
{
CtkObject lvalue = left->getRvalue(frame);
CtkObject rvalue = right->getRvalue(frame);
if (lvalue.type == CTK_INTEGER && rvalue.type == CTK_INTEGER) {
POP(frame->thread);
TOP(frame->thread).u.ivalue = lvalue.u.ivalue &= rvalue.u.ivalue;
} else {
THROW_EXCEPTION("Bad operands for & operator");
}
return lvalue;
}
CtkObject CtkXorExpr::getRvalue(CtkFrame* frame)
{
CtkObject lvalue = left->getRvalue(frame);
CtkObject rvalue = right->getRvalue(frame);
if (lvalue.type == CTK_INTEGER && rvalue.type == CTK_INTEGER) {
POP(frame->thread);
TOP(frame->thread).u.ivalue = lvalue.u.ivalue ^= rvalue.u.ivalue;
} else {
THROW_EXCEPTION("Bad operands for ^ operator");
}
return lvalue;
}
CtkObject CtkShlExpr::getRvalue(CtkFrame* frame)
{
CtkObject lvalue = left->getRvalue(frame);
CtkObject rvalue = right->getRvalue(frame);
if (lvalue.type == CTK_INTEGER && rvalue.type == CTK_INTEGER) {
POP(frame->thread);
TOP(frame->thread).u.ivalue = lvalue.u.ivalue <<= rvalue.u.ivalue & (sizeof(ctk_integer)*8-1);
} else {
THROW_EXCEPTION("Bad operands for << operator");
}
return lvalue;
}
CtkObject CtkShrExpr::getRvalue(CtkFrame* frame)
{
CtkObject lvalue = left->getRvalue(frame);
CtkObject rvalue = right->getRvalue(frame);
if (lvalue.type == CTK_INTEGER && rvalue.type == CTK_INTEGER) {
POP(frame->thread);
TOP(frame->thread).u.ivalue = lvalue.u.ivalue = (ctk_unsigned_integer)lvalue.u.ivalue >> (rvalue.u.ivalue & (sizeof(ctk_integer)*8-1));
} else {
THROW_EXCEPTION("Bad operands for >> operator");
}
return lvalue;
}
CtkObject CtkEqExpr::getRvalue(CtkFrame* frame)
{
CtkObject lvalue = left->getRvalue(frame);
CtkObject rvalue = right->getRvalue(frame);
CtkObject result;
MAKE_INTEGER(result, IS_EQUAL(lvalue, rvalue));
POP2(frame->thread);
PUSH_CS(frame->thread, result);
return result;
}
CtkObject CtkNeExpr::getRvalue(CtkFrame* frame)
{
CtkObject lvalue = left->getRvalue(frame);
CtkObject rvalue = right->getRvalue(frame);
CtkObject result;
MAKE_INTEGER(result, !IS_EQUAL(lvalue, rvalue));
POP2(frame->thread);
PUSH_CS(frame->thread, result);
return result;
}
CtkObject CtkGtExpr::getRvalue(CtkFrame* frame)
{
CtkObject lvalue = left->getRvalue(frame);
CtkObject rvalue = right->getRvalue(frame);
int result = 0;
if (lvalue.type == CTK_REAL && rvalue.type == CTK_REAL) {
result = lvalue.u.rvalue > rvalue.u.rvalue;
} else if (lvalue.type == CTK_REAL && rvalue.type == CTK_INTEGER) {
result = lvalue.u.rvalue > rvalue.u.ivalue;
} else if (rvalue.type == CTK_REAL && lvalue.type == CTK_INTEGER) {
result = lvalue.u.ivalue > rvalue.u.rvalue;
} else if (lvalue.type == CTK_INTEGER && rvalue.type == CTK_INTEGER) {
result = lvalue.u.ivalue > rvalue.u.ivalue;
} else if (lvalue.type == CTK_STRING && rvalue.type == CTK_STRING) {
result = strcmp(lvalue.u.svalue, rvalue.u.svalue) > 0;
} else {
THROW_EXCEPTION("Bad operands for > operator");
}
MAKE_INTEGER(lvalue, result);
POP2(frame->thread);
PUSH_CS(frame->thread, lvalue);
return lvalue;
}
CtkObject CtkGeExpr::getRvalue(CtkFrame* frame)
{
CtkObject lvalue = left->getRvalue(frame);
CtkObject rvalue = right->getRvalue(frame);
int result = 0;
if (lvalue.type == CTK_REAL && rvalue.type == CTK_REAL) {
result = lvalue.u.rvalue >= rvalue.u.rvalue;
} else if (lvalue.type == CTK_REAL && rvalue.type == CTK_INTEGER) {
result = lvalue.u.rvalue >= rvalue.u.ivalue;
} else if (rvalue.type == CTK_REAL && lvalue.type == CTK_INTEGER) {
result = lvalue.u.ivalue >= rvalue.u.rvalue;
} else if (lvalue.type == CTK_INTEGER && rvalue.type == CTK_INTEGER) {
result = lvalue.u.ivalue >= rvalue.u.ivalue;
} else if (lvalue.type == CTK_STRING && rvalue.type == CTK_STRING) {
result = strcmp(lvalue.u.svalue, rvalue.u.svalue) >= 0;
} else {
THROW_EXCEPTION("Bad operands for >= operator");
}
MAKE_INTEGER(lvalue, result);
POP2(frame->thread);
PUSH_CS(frame->thread, lvalue);
return lvalue;
}
CtkObject CtkLtExpr::getRvalue(CtkFrame* frame)
{
CtkObject lvalue = left->getRvalue(frame);
CtkObject rvalue = right->getRvalue(frame);
int result = 0;
if (lvalue.type == CTK_REAL && rvalue.type == CTK_REAL) {
result = lvalue.u.rvalue < rvalue.u.rvalue;
} else if (lvalue.type == CTK_REAL && rvalue.type == CTK_INTEGER) {
result = lvalue.u.rvalue < rvalue.u.ivalue;
} else if (rvalue.type == CTK_REAL && lvalue.type == CTK_INTEGER) {
result = lvalue.u.ivalue < rvalue.u.rvalue;
} else if (lvalue.type == CTK_INTEGER && rvalue.type == CTK_INTEGER) {
result = lvalue.u.ivalue < rvalue.u.ivalue;
} else if (lvalue.type == CTK_STRING && rvalue.type == CTK_STRING) {
result = strcmp(lvalue.u.svalue, rvalue.u.svalue) < 0;
} else {
THROW_EXCEPTION("Bad operands for < operator");
}
MAKE_INTEGER(lvalue, result);
POP2(frame->thread);
PUSH_CS(frame->thread, lvalue);
return lvalue;
}
CtkObject CtkLeExpr::getRvalue(CtkFrame* frame)
{
CtkObject lvalue = left->getRvalue(frame);
CtkObject rvalue = right->getRvalue(frame);
int result = 0;
if (lvalue.type == CTK_REAL && rvalue.type == CTK_REAL) {
result = lvalue.u.rvalue <= rvalue.u.rvalue;
} else if (lvalue.type == CTK_REAL && rvalue.type == CTK_INTEGER) {
result = lvalue.u.rvalue <= rvalue.u.ivalue;
} else if (rvalue.type == CTK_REAL && lvalue.type == CTK_INTEGER) {
result = lvalue.u.ivalue <= rvalue.u.rvalue;
} else if (lvalue.type == CTK_INTEGER && rvalue.type == CTK_INTEGER) {
result = lvalue.u.ivalue <= rvalue.u.ivalue;
} else if (lvalue.type == CTK_STRING && rvalue.type == CTK_STRING) {
result = strcmp(lvalue.u.svalue, rvalue.u.svalue) <= 0;
} else {
THROW_EXCEPTION("Bad operands for <= operator");
}
MAKE_INTEGER(lvalue, result);
POP2(frame->thread);
PUSH_CS(frame->thread, lvalue);
return lvalue;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -