⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compiler.cpp

📁 C-Talk is interpreted scripting language with C-like syntax and dynamic type checking. Variables in
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    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 + -