ekBool ekCompile(ekCompiler *compiler, const char *sourcePath, const char *source, ekU32 compileOpts) { struct ekContext *E = compiler->E; ekBool success = ekFalse; ekToken emptyToken = {0}; void *parser; compiler->sourcePath = sourcePath; compiler->source = source; #ifdef EUREKA_TRACE_PARSER ekParseTrace(stderr, "--- "); #endif ekTraceMem(("\n " "--- start chunk compile ---\n")); parser = ekParseAlloc(E); compiler->root = NULL; ekLex(parser, source, ekParse, compiler); ekParse(parser, 0, emptyToken, compiler); if(compiler->root) { if(ekArraySize(E, &compiler->errors)) { ekSyntaxDestroy(E, compiler->root); compiler->root = NULL; } else { if(compileOpts & ECO_OPTIMIZE) { ekCompileOptimize(E, compiler); } ekAssemble(E, compiler, ekTrue); success = ekTrue; if(!(compileOpts & ECO_KEEP_SYNTAX_TREE)) { ekSyntaxDestroy(E, compiler->root); compiler->root = NULL; }; } } ekParseFree(E, parser); ekTraceMem((" " "--- end chunk compile ---\n\n")); compiler->sourcePath = NULL; compiler->source = NULL; return success; }
static ekS32 ekCompileOptimizeChild(struct ekContext *E, ekCompiler *compiler, ekSyntax *syntax) { if(syntax->v.a) { ekCompileOptimizeArray(E, compiler, syntax->v.a); } if(syntax->v.p) { ekCompileOptimizeChild(E, compiler, syntax->v.p); } if(syntax->l.a) { ekCompileOptimizeArray(E, compiler, syntax->l.a); } if(syntax->l.p) { ekCompileOptimizeChild(E, compiler, syntax->l.p); } if(syntax->r.a) { ekCompileOptimizeArray(E, compiler, syntax->r.a); } if(syntax->r.p) { ekCompileOptimizeChild(E, compiler, syntax->r.p); } switch(syntax->type) { case EST_ADD: case EST_SUB: case EST_MUL: case EST_DIV: { // Integer arithmetic optimization if((syntax->l.p->type == EST_KINT) && (syntax->r.p->type == EST_KINT)) { ekS32 val; switch(syntax->type) { case EST_ADD: val = syntax->l.p->v.i + syntax->r.p->v.i; break; case EST_SUB: val = syntax->l.p->v.i - syntax->r.p->v.i; break; case EST_MUL: val = syntax->l.p->v.i * syntax->r.p->v.i; break; case EST_DIV: if(!syntax->r.p->v.i) { return 0; } val = syntax->l.p->v.i / syntax->r.p->v.i; break; }; ekSyntaxDestroy(E, syntax->l.p); syntax->l.p = NULL; ekSyntaxDestroy(E, syntax->r.p); syntax->r.p = NULL; syntax->type = EST_KINT; syntax->v.i = val; } } break; }; return 0; }
static void ekSyntaxElementClear(struct ekContext * E, ekSyntaxElement * e) { if (e->p) { ekSyntaxDestroy(E, e->p); } if (e->s) { ekFree(e->s); } if (e->a) { ekArrayDestroy(E, &e->a, (ekDestroyCB)ekSyntaxDestroy); } }
void ekCompilerDestroy(ekCompiler *compiler) { struct ekContext *E = compiler->E; if(compiler->chunk) { ekChunkDestroy(E, compiler->chunk); } if(compiler->root) { ekSyntaxDestroy(E, compiler->root); } ekArrayDestroy(E, &compiler->errors, (ekDestroyCB)ekErrorDestroy); ekFree(compiler); }
ekSyntax * ekSyntaxCreateStatementExpr(struct ekContext * E, ekSyntax * expr) { ekSyntax * syntax; if ((expr->type == EST_EXPRESSIONLIST) && (ekArraySize(E, &expr->v.a) == 0)) { // An empty statement. Without PYTHON_SCOPING, this only happens // when there are multiple semicolons in a row. However, when // it is enabled, one is created for every blank line! ekSyntaxDestroy(E, expr); return NULL; } syntax = ekSyntaxCreate(E, EST_STATEMENT_EXPR, expr->line); syntax->v.p = expr; return syntax; }