示例#1
0
	CValue CallFunction(
		CScope& scope,
		CStack& stack,
		const CSourceLocation& location,
		const std::string& symbol,
		const std::vector<CValue>& argValues)
	{
		// Analyze function value.
		CValue functionValue = scope.GetValue(symbol, location, stack);
		if (!IsFunction(functionValue)) {
			throw ExScopeSymbolIsNotFunction{ location, stack };
		}

		if (argValues.size() > functionValue.GetFuncArity()) {
			throw ExScopeFormalActualArgCountMismatch{ location, stack };
		}

		// Analyze function definition.
		const auto& functionDef = functionValue.GetFuncDef();
		const auto& captures = functionValue.GetFuncCaptures();
		auto applArgs = functionValue.GetAppliedArgs();
		std::copy(begin(argValues), end(argValues), std::back_inserter(applArgs));

		if (argValues.size() < functionValue.GetFuncArity()) {
			// "Curry on"...			
			return CValue::MakeFunction(&functionDef, captures, applArgs);
		}

		// Call function
		const auto& argNames = functionDef.GetFormalArgs();
		const auto& argLocations = functionDef.GetArgLocations();
		assert(argNames.size() == argLocations.size());

		unsigned argsCount = argNames.size();

		CLocalScope funcScope{ scope.GetGlobalScope() };

		for (unsigned i = 0; i < argsCount; ++i) {
			funcScope.TryRegisteringBind(
				stack, 
				argNames[i], 
				applArgs[i], 
				argLocations[i]);
		}

		for (const auto& pr : captures) {
			funcScope.TryRegisteringBind(
				stack, 
				pr.first, 
				pr.second.value, 
				pr.second.location);
		}

		stack.PushCall(symbol);
		CValue result = functionDef.Execute(funcScope, stack);
		stack.PopCall();

		return result;
	}