void PatternCompiler::visit(VariablePattern& pattern, int value) { // Assign to the variable if it isn't a throwaway. if (*pattern.name() != "_") { compiler_.compileAssignment(pattern.pos(), pattern.resolved(), value, true); } // Compile the inner pattern. if (!pattern.pattern().isNull()) { pattern.pattern()->accept(*this, value); } }
void Resolver::resolveParam(gc<Pattern> param) { VariablePattern* variable = param->asVariablePattern(); if (variable != NULL) { // It's a variable, so resolve its inner pattern. if (!variable->pattern().isNull()) { scope_->resolve(*variable->pattern()); } } else { // Not a variable, so just resolve it normally. scope_->resolve(*param); } }
void PatternParser::parseVariablePattern(Pattern* pattern, vector<string>& tokenList) { // Formats are: // PatternName VARIABLE // PatternName time1 factor1 time2 factor2 ... // ... check for enough tokens int nTokens = tokenList.size(); if ( nTokens < 2 ) throw InputError(InputError::TOO_FEW_ITEMS, ""); string* tokens = &tokenList[0]; // ... cast pattern to VariablePattern VariablePattern* varPat = static_cast<VariablePattern*>(pattern); // ... return if second token is the pattern type keyword if ( Utilities::match(tokens[1], "VARIABLE") ) return; // ... read in pairs of times and pattern factors // (times can be in decimal hours or hours:minutes format) string timeUnits(""); int seconds; double factor; int i = 1; while ( i < nTokens ) { seconds = Utilities::getSeconds(tokens[i], timeUnits); if ( seconds < 0 ) { throw InputError(InputError::INVALID_TIME, tokens[i] + " " + timeUnits); } i++; if ( i >= nTokens ) throw InputError(InputError::TOO_FEW_ITEMS, ""); if ( !Utilities::parseNumber(tokens[i], factor) ) { throw InputError(InputError::INVALID_NUMBER, tokens[i]); } varPat->addTime(seconds); varPat->addFactor(factor); i++; } }
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::compileParamField(PatternCompiler& compiler, gc<Pattern> param, int slot) { VariablePattern* variable = param->asVariablePattern(); if (variable != NULL) { // It's a variable, so compile its inner pattern. We don't worry about // the variable itself because the calling convention ensures its value // is already in the right slot. compiler.compile(variable->pattern(), slot); // If we closed over the parameter, then we don't want in a local slot, // we want it in the upvar, so create it and copy the value up. if (*variable->name() != "_" && variable->resolved()->scope() == NAME_CLOSURE) { write(variable->pos(), OP_SET_UPVAR, variable->resolved()->index(), slot, 1); } } else { // Not a variable, so just compile it normally. compiler.compile(param, slot); } }
void Compiler::declareVariables(gc<Pattern> pattern, Module* module) { RecordPattern* record = pattern->asRecordPattern(); if (record != NULL) { for (int i = 0; i < record->fields().count(); i++) { declareVariables(record->fields()[i].value, module); } return; } VariablePattern* variable = pattern->asVariablePattern(); if (variable != NULL) { declareVariable(variable->pos(), variable->name(), module); if (!variable->pattern().isNull()) { declareVariables(variable->pattern(), module); } } }
void Scope::visit(VariablePattern& pattern, int dummy) { if (*pattern.name() != "_") { if (isTopLevel()) { // It's a top-level module variable. Since these are forward declared, // they should already exist. Just look up the existing one. int module = resolver_.compiler_.getModuleIndex(resolver_.module_); int index = resolver_.module_.findVariable(pattern.name()); if (index == -1) { resolver_.compiler_.reporter().error(pattern.pos(), "Variable '%s' is not defined.", pattern.name()->cString()); // Put a fake index in so we can continue and report more errors. index = 0; } pattern.setResolved(new ResolvedName(module, index)); } else { // Declaring a local variable, so create a slot for it. gc<ResolvedName> resolved = resolver_.makeLocal(pattern.pos(), pattern.name()); pattern.setResolved(resolved); } } if (!pattern.pattern().isNull()) { pattern.pattern()->accept(*this, dummy); } }