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

📄 compiler.cpp

📁 C-Talk is interpreted scripting language with C-like syntax and dynamic type checking. Variables in
💻 CPP
📖 第 1 页 / 共 4 页
字号:
#include "compiler.h"
#include "ctkparser.h"
#include "trampoline.h"
#include <malloc.h>

#ifndef MAX_PATH_LEN
#define MAX_PATH_LEN 1024
#endif 

#define TOP(t)      (t)->stack[(t)->sp-1]
#define POP(t)      ((t)->sp -= 1)
#define POP2(t)     ((t)->sp -= 2)
#define POP4(t)     ((t)->sp -= 4)
//#define POP(t)      assert(((t)->sp -= 1) >= 0)
//#define POP2(t)     assert(((t)->sp -= 2) >= 0)
//#define POP4(t)     assert(((t)->sp -= 4) >= 0)
#define PUSH(t, o)  ((t)->stack[(t)->sp] = (o), (t)->sp += 1)
#define PUSH_CS(t, o) { \
     CtkMemoryManager::instance.beginAccess(t); \
     (t)->stack[(t)->sp] = (o); \
     (t)->sp += 1; \
     CtkMemoryManager::instance.endAccess(t); }

#define PUSH_CHECK(t, o) \
     if ((t)->sp == (t)->stackSize) ctkThrowException("Stack overflow"); \
     else ((t)->stack[(t)->sp] = (o), (t)->sp += 1)

#define PUSH_CHECK_CS(t, o) { \
     CtkMemoryManager::instance.beginAccess(t); \
     if ((t)->sp == (t)->stackSize) { \
         ctkThrowException("Stack overflow"); \
     } else { \
         (t)->stack[(t)->sp] = (o); \
         (t)->sp += 1; \
     } \
     CtkMemoryManager::instance.endAccess(t); }

#define THROW_EXCEPTION(x) (frame->call = this, ctkThrowException(x))

CtkCompiler CtkCompiler::instance;

CtkObject CtkExpr::getLvalue(CtkFrame* frame) { 
    THROW_EXCEPTION("Lvalue expected");
    return ctkNull;
}

void CtkExpr::setLvalue(CtkFrame* frame, CtkObject) { 
    THROW_EXCEPTION("Lvalue expected");
}

void CtkExpr::assign(CtkFrame* frame, CtkObject) { 
    THROW_EXCEPTION("Lvalue expected");
}

bool CtkExpr::isLvalue() { 
    return false;
}

CtkFuncDef* CtkExpr::getFuncDef() { 
    return NULL;
}

void CtkExpr::compile(CtkCompiler*, CompileCtx) {}

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


void CtkStmt::compile(CtkCompiler*) {}

JumpType CtkStmt::execute(CtkFrame*) { 
    return JMP_NEXT;
}

JumpType CtkStmt::executeBlock(CtkFrame* frame) { 
    CtkStmt* stmt = this;
    while (stmt != NULL) { 
	JumpType jump = stmt->execute(frame);
	if (jump != JMP_NEXT) { 
	    return jump;
	}
	stmt = stmt->next;
    }
    return JMP_NEXT;
}


#ifdef _WIN32
#define FILE_SEP '\\'
#else
#define FILE_SEP '/'
#endif

CtkModule::~CtkModule()
{
    delete[] path;
    delete   ctx;
    delete   prog;
}

void CtkCompiler::reset()
{
    CtkModule *mod, *nextMod;
    for (mod = modules; mod != NULL; mod = nextMod) {         
        nextMod = mod->next;
        delete mod;
    }
    
    CtkImport *imp, *nextImp;
    for (imp = importList; imp != NULL; imp = nextImp) { 
        nextImp = imp->next;
        delete imp;
    }    
    program = NULL;
    modules = NULL;
    importList = NULL;
}

void CtkCompiler::compileBlock(CtkStmt* stmts) { 
    CtkSymbol* beforeSymbols = currCtx->symbols;
    while (stmts != NULL) { 
	stmts->compile(this);
	stmts = stmts->next;
    }
    CtkSymbol* afterSymbols = currCtx->symbols;
    while (beforeSymbols != afterSymbols) {
	CtkSymbol* symbol = afterSymbols;
	afterSymbols = afterSymbols->next;
	delete symbol;
    }
    currCtx->symbols = beforeSymbols;
}

extern int yyparse();

CtkModule* CtkCompiler::compile(char const* moduleName)
{
    critical_section cs(mutex);
    return compile(CtkSymbolTable::instance.add(moduleName, IDENT));
}
    
CtkModule* CtkCompiler::compile(CtkToken* moduleName)
{
    critical_section cs(mutex);
    for (CtkModule* module = modules; module != NULL; module = module->next) { 
	if (module->tkn->symId == moduleName->symId) {  
	    return module;
	}
    }	 
    for (CtkPath* p = path; p != NULL; p = p->next) { 
	char buf[MAX_PATH_LEN];
	sprintf(buf, "%s%c%s.ctk", p->dir, FILE_SEP, moduleName->name);
	FILE* f = fopen(buf, "r");
	if (f != NULL) { 
	    CtkScanner::instance.reset(f);
	    CtkModule* saveCurrModule = currModule;
	    CtkModule* curr = new CtkModule(moduleName, buf, modules);
	    currModule = modules = curr;
	    yyparse();
	    fclose(f);
	    program->compile(this);
	    int nVars = curr->prog->nVars;	
	    CtkThread* currThread = ctkGetCurrentThread();
	    CtkMemoryManager::instance.beginAccess(currThread);
	    CtkFrame* frame = 
		(CtkFrame*)ctkAllocateObject(sizeof(CtkFrame) 
					     + (nVars-1)*sizeof(CtkObject), NULL);
	    frame->nVars = nVars;
	    frame->call = NULL;
	    frame->up = NULL;
	    memset(frame->vars, 0, nVars*sizeof(CtkObject));
	    curr->frame = frame;
	    CtkFunction* func = (CtkFunction*)ctkAllocateObject(sizeof(CtkFunction), NULL);
	    func->nestedLevel = 0;
	    func->nParams = 0;
	    func->nLocalVars = nVars;
	    func->next = NULL;
	    func->exterior = NULL;
	    func->stmts = curr->prog->stmts; 
	    func->name = "<main>";
	    func->module = curr;
	    frame->func = func;
	    CtkFrame* topFrame = currThread->currFrame;
	    if (topFrame == NULL) { 
		currThread->currFrame = currThread->callStack = frame;
	    } else { 
		topFrame->up = frame;
	    }
	    frame->thread = currThread;
	    CtkMemoryManager::instance.endAccess(currThread);
	    curr->prog->execute(curr->frame);
	    currModule = saveCurrModule;
	    currThread->currFrame = topFrame;
	    if (topFrame != NULL) { 
		topFrame->up = NULL;
	    }
	    return curr;
	} 
    }
    return NULL;
}

void CtkCompiler::error(char const* errText, CtkNode* node)
{
    ctkTrace("%s:%d: %s\n", currModule->path, node->line, errText);
    exit(1);
}


void CtkProgram::compile(CtkCompiler* compiler) { 
    CtkImport* saveImport = compiler->importList;
    compiler->importList = NULL;
    for (CtkTokenList* imp = modules; imp != NULL; imp = imp->next) { 
	CtkModule* module = compiler->compile(imp->tkn);  
	if (module == NULL) { 
	    char buf[256];
	    sprintf(buf, "Module %s not found", imp->tkn->name);
	    compiler->error(buf, stmts);
	}
	compiler->importList = new CtkImport(module, compiler->importList);
    }
    CtkContext* ctx = new CtkContext();
    ctx->nSymbols = 0;
    ctx->symbols = NULL;
    ctx->exterior = NULL;
    compiler->currCtx = ctx;
    for (CtkStmt* stmt = stmts; stmt != NULL; stmt = stmt->next) { 
	 stmt->compile(compiler);	 
    }
    nVars = ctx->nSymbols;
    compiler->currModule->ctx = ctx;
    compiler->currModule->prog = this;
    compiler->importList = saveImport;
}

JumpType CtkProgram::execute(CtkFrame* frame)
{
    CtkThread* currThread = (CtkThread*)ctkGetCurrentThread();
#ifdef USE_CTALK_EXCEPTION
    try {
#else
    jmp_buf buf;
    jmp_buf* saveBuf = currThread->catchCtx;
    currThread->catchCtx = &buf;
    if (setjmp(buf) == 0) { 
#endif
	for (CtkStmt* stmt = stmts; stmt != NULL; stmt = stmt->next) { 
            JumpType jump = stmt->execute(frame);
	    switch (jump) { 
	      case JMP_EXCEPTION:
		ctkTrace("Uncatched exception %s\n", 
			IF_STRING(currThread->exceptionObject));
		ctkPrintStackTrace(frame);
		exit(1);
	      case JMP_RETURN:
#ifndef USE_CTALK_EXCEPTION
                currThread->catchCtx = saveBuf;
#endif
		return JMP_RETURN;
	      case JMP_NEXT:
		continue;
	      default:
		assert(false);
	    }
	} 
#ifndef USE_CTALK_EXCEPTION
        currThread->catchCtx = saveBuf;
#endif
#ifdef USE_CTALK_EXCEPTION
    } catch (CtkException const& x) {
#else
    } else { 
        currThread->catchCtx = saveBuf;
#endif
	ctkTrace("Uncatched exception %s\n", 
		IF_STRING(currThread->exceptionObject));
	ctkPrintStackTrace(frame);
	exit(1);
    }
    return JMP_NEXT;
}

void CtkIfStmt::compile(CtkCompiler* compiler)
{
    cond->compile(compiler);
    compiler->compileBlock(thenStmt);
    if (elseStmt != NULL) { 
	compiler->compileBlock(elseStmt);
    }
}

JumpType CtkIfStmt::execute(CtkFrame* frame)
{
    if (cond->testCondition(frame)) { 
	return thenStmt->executeBlock(frame);
    } else if (elseStmt != NULL) { 
	return elseStmt->executeBlock(frame);
    } else { 
	return JMP_NEXT;
    }
}

void CtkForStmt::compile(CtkCompiler* compiler)
{
    if (init != NULL) { 
	init->compile(compiler);
    }
    if (cond != NULL) { 
	cond->compile(compiler);
    }
    if (inc != NULL) { 
	inc->compile(compiler);
    }
    compiler->compileBlock(body);
}

JumpType CtkForStmt::execute(CtkFrame* frame)
{
    if (init != NULL) { 
	init->evaluate(frame);
    }
    while (cond == NULL || cond->testCondition(frame)) { 
	JumpType jump = body->executeBlock(frame);
	switch (jump) { 
	  case JMP_NEXT:
	  case JMP_CONTINUE:
	    break;
	  case JMP_BREAK:
	    return JMP_NEXT;	    
	  default:
	    return jump;
	}
	if (inc != NULL) { 
	    inc->evaluate(frame);
	}
    }
    return JMP_NEXT;	    
}


void CtkDoWhileStmt::compile(CtkCompiler* compiler)
{
    compiler->compileBlock(body);
    cond->compile(compiler);
}

JumpType CtkDoWhileStmt::execute(CtkFrame* frame)
{
    do { 
	JumpType jump = body->executeBlock(frame);
	switch (jump) { 
	  case JMP_NEXT:
	  case JMP_CONTINUE:
	    break;
	  case JMP_BREAK:
	    return JMP_NEXT;	    
	  default:
	    return jump;
	}	
    } while (cond->testCondition(frame));

    return JMP_NEXT;	    
}


void CtkWhileStmt::compile(CtkCompiler* compiler)
{
    cond->compile(compiler);
    compiler->compileBlock(body);
}

JumpType CtkWhileStmt::execute(CtkFrame* frame)
{
    while (cond->testCondition(frame)) { 
	JumpType jump = body->executeBlock(frame);
	switch (jump) { 
	  case JMP_NEXT:
	  case JMP_CONTINUE:
	    break;
	  case JMP_BREAK:
	    return JMP_NEXT;	    
	  default:
	    return jump;
	}	
    }
    return JMP_NEXT;	    
}



void CtkSwitchStmt::compile(CtkCompiler* compiler)
{
    expr->compile(compiler);
    for (CtkCaseStmt* cnode = cases; cnode != NULL; cnode = cnode->next) { 
	if (cnode->selector != NULL) { 
	    cnode->selector->compile(compiler);
	}
	compiler->compileBlock(cnode->stmt);
    }
}

JumpType CtkSwitchStmt::execute(CtkFrame* frame)
{
    CtkCaseStmt* selectedNode = NULL;
    CtkObject value = expr->getRvalue(frame);
    for (CtkCaseStmt* cnode = cases; cnode != NULL; cnode = cnode->next) { 
	if (cnode->selector != NULL) { 
	    CtkObject selector = cnode->selector->getRvalue(frame);
	    if (IS_EQUAL(selector, value)) { 
		POP(frame->thread);
		selectedNode = cnode;
		break;
	    }
	    POP(frame->thread);
	} else { 
	    selectedNode = cnode;
	}
    }
    POP(frame->thread);
    while (selectedNode != NULL) { 
	JumpType jump = selectedNode->stmt->executeBlock(frame);
	switch (jump) { 
	  case JMP_BREAK:
	    return JMP_NEXT;
	  case JMP_NEXT:
	    selectedNode = selectedNode->next;
	    continue;
	  default:
	    return jump;
	}
    }
    return JMP_NEXT;
}


JumpType CtkBreakStmt::execute(CtkFrame* frame)
{
    return JMP_BREAK;
}


JumpType CtkContinueStmt::execute(CtkFrame* frame)
{
    return JMP_CONTINUE;
}

void CtkReturnStmt::compile(CtkCompiler* compiler)
{
    if (expr != NULL) { 
	expr->compile(compiler);
    }
}

JumpType CtkReturnStmt::execute(CtkFrame* frame)
{    
    if (expr != NULL) { 
	expr->getRvalue(frame);
    } else { 
	PUSH_CHECK_CS(frame->thread, ctkNull);
    }
    return JMP_RETURN;
}



void CtkThrowStmt::compile(CtkCompiler* compiler)
{
    except->compile(compiler);
}

JumpType CtkThrowStmt::execute(CtkFrame* frame)
{
    CtkThread* currThread = frame->thread;
    frame->call = this;
    currThread->exceptionObject = except->getRvalue(frame);
    POP(currThread);
    return JMP_EXCEPTION;
}

void CtkTryStmt::compile(CtkCompiler* compiler)
{

⌨️ 快捷键说明

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