} while (changed);
}
-struct FindLocals: Visitor
+struct ScanFunctionBody: Visitor
{
using Visitor::visit;
+ // search for locals
QList<QStringRef> locals;
+ bool directEval;
+
+ ScanFunctionBody()
+ : directEval(false)
+ {
+ }
+
+ void operator()(Node *node) {
+ directEval = false;
+ locals.clear();
+ if (node)
+ node->accept(this);
+ }
+
+protected:
+ virtual bool visit(CallExpression *ast)
+ {
+ if (! directEval) {
+ if (IdentifierExpression *id = cast<IdentifierExpression *>(ast->base)) {
+ if (id->name == QLatin1String("eval")) {
+ directEval = true;
+ }
+ }
+ }
+ return true;
+ }
virtual bool visit(VariableDeclaration *ast)
{
_module = module;
IR::Function *globalCode = _module->newFunction(QLatin1String("%entry"));
+ globalCode->directEval = true; // ### remove
_function = globalCode;
_block = _function->newBasicBlock();
_exitBlock = _function->newBasicBlock();
if (ast->expression) {
Result expr = expression(ast->expression);
- if (expr.code)
+ if (! expr.code)
+ expr.code = _block->CONST(IR::UndefinedType, 0);
+
+ if (! _function->directEval) {
+ const int index = tempForLocalVariable(ast->name);
+ if (index != -1) {
+ _block->MOVE(_block->TEMP(index), *expr);
+ return;
+ }
+ } else {
_block->MOVE(_block->NAME(ast->name.toString(), ast->identifierToken.startLine, ast->identifierToken.startColumn), *expr);
+ }
}
}
bool Codegen::visit(IdentifierExpression *ast)
{
+ if (! _function->directEval) {
+ int index = tempForLocalVariable(ast->name);
+ if (index != -1) {
+ _expr.code = _block->TEMP(index);
+ return false;
+ }
+ }
+
_expr.code = _block->NAME(ast->name.toString(),
ast->identifierToken.startLine,
ast->identifierToken.startColumn);
+
return false;
}
void Codegen::defineFunction(FunctionExpression *ast, bool /*isDeclaration*/)
{
+ ScanFunctionBody functionInfo;
+ functionInfo(ast->body);
+
IR::Function *function = _module->newFunction(ast->name.toString());
IR::BasicBlock *entryBlock = function->newBasicBlock();
IR::BasicBlock *exitBlock = function->newBasicBlock();
+
+ if (! functionInfo.directEval) {
+ for (int i = 0; i < functionInfo.locals.size(); ++i) {
+ unsigned t = entryBlock->newTemp();
+ Q_ASSERT(t == unsigned(i));
+ entryBlock->MOVE(entryBlock->TEMP(t), entryBlock->CONST(IR::UndefinedType, 0));
+ }
+ }
+
unsigned returnAddress = entryBlock->newTemp();
entryBlock->MOVE(entryBlock->TEMP(returnAddress), entryBlock->CONST(IR::UndefinedType, 0));
_function->RECEIVE(it->name.toString());
}
- FindLocals locals;
- if (ast->body)
- ast->body->accept(&locals);
-
- foreach (const QStringRef &local, locals.locals) {
+ foreach (const QStringRef &local, functionInfo.locals) {
_function->LOCAL(local.toString());
}
}
}
+int Codegen::tempForLocalVariable(const QStringRef &string) const
+{
+ for (int i = 0; i < _function->locals.size(); ++i) {
+ if (*_function->locals.at(i) == string)
+ return i;
+ }
+ return -1;
+}
+
bool Codegen::visit(IdentifierPropertyName *ast)
{
_property = ast->id.toString();