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

📄 compiler.cpp

📁 C-Talk is interpreted scripting language with C-like syntax and dynamic type checking. Variables in
💻 CPP
📖 第 1 页 / 共 4 页
字号:
CtkObject CtkEnvExpr::getLvalue(CtkFrame* frame) 
{
    CtkObject base = expr->getRvalue(frame);
    char* value = getenv(TO_STRING(base));
    CtkMemoryManager::instance.beginAccess(frame->thread);
    PUSH_CHECK(frame->thread, ctkNull);
    if (value == NULL) { 
	PUSH_CHECK(frame->thread, ctkNull);
	CtkMemoryManager::instance.endAccess(frame->thread);
	return ctkNull;
    }
    CtkObject result;
    result.u.svalue = (char*)ctkAllocateObject(strlen(value)+1, NULL);
    strcpy(result.u.svalue, value);
    result.type = CTK_STRING;
    PUSH_CHECK(frame->thread, result);
    CtkMemoryManager::instance.endAccess(frame->thread);
    return result;
}

void CtkEnvExpr::assign(CtkFrame* frame, CtkObject value)
{
    CtkObject name = expr->getRvalue(frame);
    char* nam = TO_STRING(name);
    char* val = TO_STRING(value);
    char* buf = (char*)alloca(strlen(nam) + strlen(val) + 2);
    sprintf(buf, "%s=%s", nam, val);
    putenv(buf);
    POP(frame->thread);
}

void CtkEnvExpr::setLvalue(CtkFrame* frame, CtkObject value)
{
    POP2(frame->thread);
    char* nam = TO_STRING(TOP(frame->thread));
    char* val = TO_STRING(value);
    char* buf = (char*)alloca(strlen(nam) + strlen(val) + 2);
    sprintf(buf, "%s=%s", nam, val);
    putenv(buf);
    POP(frame->thread);
}

bool CtkEnvExpr::isLvalue() { 
    return true;
}

void CtkArrayAccessExpr::compile(CtkCompiler* compiler, CompileCtx) 
{ 
    array->compile(compiler);
    index->compile(compiler);
}

CtkObject CtkArrayAccessExpr::getRvalue(CtkFrame* frame)
{
    CtkObject base = array->getRvalue(frame);
    CtkObject key = index->getRvalue(frame);
    if (base.type != CTK_ARRAY) { 
	THROW_EXCEPTION("Applying index to non-array type");
    }
    CtkObject result = ctkGetArray((CtkArray*)base.u.ptr, key);
    POP2(frame->thread);
    PUSH_CS(frame->thread, result);
    return result;
}

CtkObject CtkArrayAccessExpr::getLvalue(CtkFrame* frame) 
{
    CtkObject base = array->getRvalue(frame);
    CtkObject key = index->getRvalue(frame);
    if (base.type != CTK_ARRAY) { 
	THROW_EXCEPTION("Applying index to non-array type");
    }
    CtkMemoryManager::instance.beginAccess(frame->thread);
    CtkObject result = ctkGetArray((CtkArray*)base.u.ptr, key);
    PUSH_CHECK(frame->thread, result);
    CtkMemoryManager::instance.endAccess(frame->thread);
    return result;
}


void CtkArrayAccessExpr::assign(CtkFrame* frame, CtkObject value)
{
    CtkObject base = array->getRvalue(frame);
    CtkObject key = index->getRvalue(frame);
    if (base.type != CTK_ARRAY) { 
	THROW_EXCEPTION("Applying index to non-array type");
    }
    CtkMemoryManager::instance.beginAccess(frame->thread); 
    ctkPutArray((CtkArray*)base.u.ptr, key, value);
    POP2(frame->thread);
    CtkMemoryManager::instance.endAccess(frame->thread); 
}

void CtkArrayAccessExpr::setLvalue(CtkFrame* frame, CtkObject value)
{
    CtkMemoryManager::instance.beginAccess(frame->thread); 
    ctkPutArray((CtkArray*)frame->thread->stack[frame->thread->sp-3].u.ptr, 
		frame->thread->stack[frame->thread->sp-2], value);
    frame->thread->sp -= 3;
    CtkMemoryManager::instance.endAccess(frame->thread); 
}

bool CtkArrayAccessExpr::isLvalue() { 
    return true;
}

void CtkFuncCallExpr::compile(CtkCompiler* compiler, CompileCtx)
{
    func->compile(compiler);
    int n = 0;
    for (CtkExpr* arg = args; arg != NULL; arg = arg->next, n++) { 
	arg->compile(compiler);
    }
    CtkFuncDef* fdef = func->getFuncDef();
    if (fdef != NULL && fdef->nParams != n) {  
	char buf[256];
	sprintf(buf, "Too %s parameters for function %s", 
		fdef->nParams < n ? "many" : "few", fdef->tok->name);	
	compiler->error(buf, func);
    }
    nArgs = n;
}

static CtkObject ctkDllFunctionTrampoline(CtkPrimitive* prim, int nArgs, CtkObject* args)
{
    if (nArgs >= MAX_DLL_FUNC_ARGS) { 
	char buf[256];
	sprintf(buf, "Attempt to pass %d arguments to DLL function %s (limit for maximal number of arguments is %d)", 
		nArgs, prim->name, MAX_DLL_FUNC_ARGS);	
	ctkThrowException(buf);
    }
    int profile = 1 << nArgs;
    for (int i = 0; i < nArgs; i++) { 
        switch (args[i].type) { 
          case CTK_INTEGER:
            profile |= 1 << i;
            break;
          case CTK_REAL:
            ctkThrowException("Real type of parameter is not supported for transparent DLL invocations");
        }
    }
    void* rc = ctkTrampoline[profile]((void*)prim->func, args);
    CtkObject result;
    MAKE_RAW_POINTER(result, rc);
    return result;                    
}

CtkObject CtkFuncCallExpr::getRvalue(CtkFrame* frame)
{
    CtkObject f = func->getRvalue(frame);
    if (f.type == CTK_STRING) { 
	CtkPrimitive* prim = ctkGetPrimitive(f.u.svalue);
	if (prim != NULL) { 
	    MAKE_PRIMITIVE(f, prim);
	} else { 
	    CtkFunction* func = ctkGetFunction(f.u.svalue);
	    if (func != NULL) { 
		MAKE_FUNCTION(f, func);
	    } else {
                void* dllFunc = ctkFindFunction(f.u.svalue);
                if (dllFunc != NULL) { 
                    prim = new CtkPrimitive(f.u.svalue, (CtkPrimitiveFunc)dllFunc, false, &ctkDllFunctionTrampoline);
                    MAKE_PRIMITIVE(f, prim);
                } else { 
                    char buf[256];
                    sprintf(buf, "Function %s not found", f.u.svalue);
                    THROW_EXCEPTION(buf);
                }
	    }
	} 
    }
    frame->call = func;
    if (f.type == CTK_PRIMITIVE) { 
	CtkPrimitive* p = (CtkPrimitive*)f.u.ptr;
	CtkObject* params = (CtkObject*)alloca(nArgs*sizeof(CtkObject));
	int n = 0;
	for (CtkExpr* arg = args; arg != NULL; arg = arg->next) { 
	    params[n++] = arg->getRvalue(frame);	    
	}
	CtkMemoryManager::instance.beginAccess(frame->thread);
	frame->thread->sp -= n + 1;
	frame->thread->currFrame = frame;
	CtkObject result = p->trampoline(p, n, params);
	PUSH_CHECK(frame->thread, result);
	CtkMemoryManager::instance.endAccess(frame->thread);
	return result;
    }
    if (f.type != CTK_FUNCTION) { 
	THROW_EXCEPTION("Attempt to call non-function object");
    }
    CtkFunction* fp = (CtkFunction*)f.u.ptr;
    if (fp->nParams != nArgs) { 
	THROW_EXCEPTION("Number of actual and formal parameters doesn't match");
    }
    CtkMemoryManager::instance.beginAccess(frame->thread); 
    CtkFrame* callFrame = ctkCreateFrame(fp);
    CtkFrame* up = frame->up;
    frame->up = callFrame;
    callFrame->thread = frame->thread;
    int n = 0;
    for (CtkExpr* arg = args; arg != NULL; arg = arg->next) { 
	CtkObject value = arg->getRvalue(frame);
	callFrame->vars[n++] = value;
	POP(frame->thread);
    }
    CtkStmt* stmts = fp->stmts;
    POP(frame->thread);
    CtkMemoryManager::instance.endAccess(frame->thread); 
    switch (stmts->executeBlock(callFrame)) { 
      case JMP_RETURN:
	frame->up = up;
	return TOP(frame->thread);
      case JMP_BREAK:
	THROW_EXCEPTION("Invalid use of BREAK statement");
      case JMP_CONTINUE:
	THROW_EXCEPTION("Invalid use of CONTINUE statement");
      case JMP_NEXT:
	frame->up = up;
	PUSH_CHECK_CS(frame->thread, ctkNull);
	return ctkNull;
      case JMP_EXCEPTION:
	ctkPropagateException();
    }
    return ctkNull;
}

CtkObject CtkRunThreadExpr::getRvalue(CtkFrame* frame)
{
    CtkObject f = func->getRvalue(frame);
    if (f.type != CTK_FUNCTION) { 
	THROW_EXCEPTION("Attemp to call non-function object");
    }
    CtkFunction* fp = (CtkFunction*)f.u.ptr;
    if (fp->nParams != nArgs) { 
	THROW_EXCEPTION("Number of actual and formal parameters doesn't match");
    }
    CtkFrame* callFrame = ctkCreateFrame(fp);
    frame->call = func;
    int n = 0;
    CtkMemoryManager::instance.beginAccess(frame->thread);
    for (CtkExpr* arg = args; arg != NULL; arg = arg->next) { 
	callFrame->vars[n++] = arg->getRvalue(frame);
    }
    CtkThread* thr = ctkCreateThread(ctkRunThread, callFrame, CTK_MIN_STACK_SIZE);
    CtkObject result;
    MAKE_THREAD(result, thr);
    frame->thread->sp -= n + 1;
    PUSH_CHECK(frame->thread, result);
    CtkMemoryManager::instance.endAccess(frame->thread);
    return result;
}

CtkObject CtkIntConst::getRvalue(CtkFrame* frame)
{
    PUSH_CHECK_CS(frame->thread, value);
    return value;
}

CtkObject CtkRealConst::getRvalue(CtkFrame* frame)
{
    PUSH_CHECK_CS(frame->thread, value);
    return value;
}

CtkObject CtkNullConst::getRvalue(CtkFrame* frame)
{
    PUSH_CHECK_CS(frame->thread, ctkNull);
    return ctkNull;
}

CtkObject CtkStringConst::getRvalue(CtkFrame* frame)
{
    PUSH_CHECK_CS(frame->thread, value);
    return value;
}

void CtkArrayElemExpr::compile(CtkCompiler* compiler, CompileCtx)
{
    key->compile(compiler);
    value->compile(compiler);
}
	
void CtkArrayConst::compile(CtkCompiler* compiler, CompileCtx)
{
    int i = 0;
    for (CtkArrayElemExpr* elem = elements; elem != NULL; i++, elem = (CtkArrayElemExpr*)elem->next) {        
        if (elem->key == NULL) { 
            elem->key = new CtkIntConst(i);
        }
	elem->compile(compiler, CC_RVALUE);
    }
}
 
CtkObject CtkArrayConst::getRvalue(CtkFrame* frame)
{
    CtkMemoryManager::instance.beginAccess(frame->thread);
    CtkArray* array = ctkCreateArray();
    for (CtkArrayElemExpr* elem = elements; elem != NULL; elem = (CtkArrayElemExpr*)elem->next) {
	CtkObject key = elem->key->getRvalue(frame);
	CtkObject value = elem->value->getRvalue(frame);
	ctkPutArray(array, key, value);
	POP2(frame->thread);
    }
    CtkObject result;
    MAKE_ARRAY(result, array);
    PUSH_CHECK(frame->thread, result);
    CtkMemoryManager::instance.endAccess(frame->thread);
    return result;
}

void CtkVariable::compile(CtkCompiler* compiler, CompileCtx cc)
{
    int ctxLevel = 0;
    CtkContext* ctx;
    prim = NULL;
    func = NULL;
    for (ctx = compiler->currCtx; ctx != NULL; ctxLevel++, ctx = ctx->exterior) {
	for (CtkSymbol* symb = ctx->symbols; symb != NULL; symb = symb->next) { 
	    if (symb->tok == tok) { 
		level = ctxLevel;
		index = symb->index;
		func = symb->func;
		module = NULL;
		if (cc != CC_RVALUE && func != NULL) { 
		    compiler->error("Function is not l-value", this);
		}	    
		return;
	    }
	}
    }
    for (CtkImport* imp = compiler->importList; imp != NULL; imp = imp->next) {
	ctx = imp->module->ctx;
	for (CtkSymbol* symb = ctx->symbols; symb != NULL; symb = symb->next) { 
	    if (symb->tok == tok) { 
		index = symb->index;
		func = symb->func;
		module = imp->module->frame;
		if (cc != CC_RVALUE && func != NULL) { 
		    compiler->error("Function is not l-value", this);
		}	    
		return;
	    }
	}
    }
    // no symbol was found
    if (cc == CC_RVALUE) { 
	if ((prim = ctkGetPrimitive(tok->name)) == NULL) { 
            void* dllFunc = ctkFindFunction(tok->name);
            if (dllFunc != NULL) { 
                prim = new CtkPrimitive(tok->name, (CtkPrimitiveFunc)dllFunc, false, &ctkDllFunctionTrampoline);
            } else { 
                char buf[256];
                sprintf(buf, "Access to uninitialized variable %s", tok->name);
                compiler->error(buf, this);
            }
        }
    } else {
	level = 0;
	index = compiler->currCtx->nSymbols++;
	module = NULL;
	compiler->currCtx->symbols = new CtkSymbol(tok, index, 
						   compiler->currCtx->symbols); 
    }
}

CtkFuncDef* CtkVariable::getFuncDef() { 
    return func;
}


CtkObject CtkVariable::getRvalue(CtkFrame* frame)
{
    CtkObject result;
    if (prim != NULL) { 
	MAKE_PRIMITIVE(result, prim);
    } else if (module != NULL) { 
	result = module->vars[index];
    } else {
	CtkFrame* scope = frame;
	for (int n = level; --n >= 0; scope = scope->func->exterior); 
	result = scope->vars[index];
    }
    PUSH_CHECK_CS(frame->thread, result);
    return result;
}

CtkObject CtkVariable::getLvalue(CtkFrame* frame)
{
    PUSH_CHECK_CS(frame->thread, ctkNull);
    PUSH_CHECK_CS(frame->thread, ctkNull);
    return getRvalue(frame); 
}

void CtkVariable::assign(CtkFrame* frame, CtkObject value)
{
    CtkMemoryManager::instance.beginAccess(frame->thread); 
    if (module != NULL) { 
        module->vars[index] = value;
    } else { 
	CtkFrame* scope = frame;
	for (int n = level; --n >= 0; scope = scope->func->exterior); 
	scope->vars[index] = value;
    }    
    CtkMemoryManager::instance.endAccess(frame->thread); 	
}

bool CtkVariable::isLvalue() 
{ 
    return true;
}

void CtkVariable::setLvalue(CtkFrame* frame, CtkObject value)
{
    assign(frame, value);
    frame->thread->sp -= 3;
}


void CtkFuncDef::compile(CtkCompiler* compiler)
{
    CtkContext* exterior = compiler->currCtx;
    for (CtkContext* cpp = compiler->currCtx; cpp != NULL; cpp = cpp->exterior) {
	for (CtkSymbol* symb = cpp->symbols; symb != NULL; symb = symb->next) { 
	    if (symb->tok == tok) { 
		compiler->error("Symbol is already defined", this);
		return;
	    }
	}
    }
    index = compiler->currCtx->nSymbols++;
    CtkSymbol* symb = new CtkSymbol(tok, index, compiler->currCtx->symbols); 
    symb->func = this;
    compiler->currCtx->symbols = symb;
    CtkContext ctx;
    CtkSymbol* next = NULL;
    int n = 0;
    for (CtkTokenList* p = params; p != NULL; p = p->next) { 
	next = new CtkSymbol(p->tkn, n++, next);
    }
    ctx.nSymbols = nParams = n;
    ctx.symbols = next;
    ctx.exterior = exterior;
    compiler->currCtx = &ctx;
    compiler->currLevel += 1;
    compiler->compileBlock(stmts);
    compiler->currCtx = exterior;
    compiler->currLevel -= 1;
    nLocals = ctx.nSymbols;
}

JumpType CtkFuncDef::execute(CtkFrame* frame)
{
    CtkMemoryManager::instance.beginAccess(frame->thread); 
    CtkFunction* func = (CtkFunction*)ctkAllocateObject(sizeof(CtkFunction), NULL);
    func->stmts = stmts;
    func->nestedLevel = frame->func->nestedLevel + 1;
    func->nParams = nParams;
    func->nLocalVars = nLocals;
    func->module = frame->func->module;
    func->name = tok->name;
    func->exterior = frame;
    if (func->nestedLevel == 1) { 
	ctkAddFunction(func);
    }
    CtkObject f;
    MAKE_FUNCTION(f, func);
    frame->vars[index] = f;
    CtkMemoryManager::instance.endAccess(frame->thread); 
    return JMP_NEXT;
}











⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -