void Resolver::makeParamSlot(gc<Pattern> param) { VariablePattern* variable = param->asVariablePattern(); if (variable != NULL && *variable->name() != "_") { // It's a variable, so create a named local for it and resolve the // variable. variable->setResolved(makeLocal(param->pos(), variable->name())); // Note that we do *not* resolve the variable's inner pattern here. We // do that after all param slots are resolved so that we can ensure the // param slots are contiguous. } else { // We don't have a variable for this parameter, but the argument // will still be on the stack, so make an unnamed slot for it. makeLocal(param->pos(), String::format("(%d)", unnamedSlotId_++)); } }
void ExprCompiler::compile(Module* module, int maxLocals, gc<Pattern> leftParam, gc<Pattern> rightParam, gc<Pattern> valueParam, gc<Expr> body) { currentFile_ = chunk_->addFile(module->source()); module_ = module; // Reserve slots up front for all of the locals. This ensures that // temps will always be after locals. // TODO(bob): Using max here isn't optimal. Ideally a given temp only // needs to be after the locals that are in scope during the duration // of that temp. But calculating that is a bit hairy. For now, until we // have a more advanced compiler, this is a simple solution. numLocals_ = maxLocals; maxSlots_ = MAX(maxSlots_, numLocals_); PatternCompiler compiler(*this, true); // Track the slots used for the arguments and result. This code here // must be kept carefully in sync with the similar prelude code in // Resolver. int numParamSlots = 0; // Evaluate the method's parameter patterns. compileParam(compiler, leftParam, numParamSlots); compileParam(compiler, rightParam, numParamSlots); compileParam(compiler, valueParam, numParamSlots); // The result slot is just after the param slots. compile(body, numParamSlots); write(body->pos(), OP_RETURN, numParamSlots); ASSERT(numTemps_ == 0, "Should not have any temps left."); compiler.endJumps(); }