Пример #1
0
		AST::Value CallValue(Context& context, AST::Value rawValue, HeapArray<AST::Value> args, const Debug::SourceLocation& location) {
			auto value = derefValue(std::move(rawValue));
			
			if (getDerefType(value.type())->isTypename()) {
				return CallValue(context, GetStaticMethod(context, std::move(value), context.getCString("create"), location), std::move(args), location);
			}
			
			if (!value.type()->isCallable()) {
				// Try to use 'call' method.
				if (TypeCapabilities(context).hasCallMethod(getDerefType(value.type()))) {
					return CallValue(context, GetMethod(context, std::move(value),
					                                    context.getCString("call"), location),
					                 std::move(args), location);
				} else {
					context.issueDiag(TypeNotCallableDiag(getDerefType(value.type())),
					                  location);
					return AST::Value::Constant(Constant::Integer(0), context.typeBuilder().getIntType());
				}
			}
			
			const auto functionType = value.type()->asFunctionType();
			const auto& typeList = functionType.parameterTypes();
			
			if (functionType.attributes().isVarArg()) {
				if (args.size() < typeList.size()) {
					context.issueDiag(VarArgTooFewArgsDiag(value.toDiagString(),
					                                       args.size(), typeList.size()),
					                  location);
				}
			} else {
				if (args.size() != typeList.size()) {
					context.issueDiag(CallIncorrectArgCountDiag(value.toDiagString(),
					                                            args.size(), typeList.size()),
					                  location);
				}
			}
			
			if (!TypeCapabilities(context).isSized(functionType.returnType())) {
				// TODO: also check that the type is not abstract.
				context.issueDiag(CallReturnTypeIsUnsizedDiag(functionType.returnType()),
				                  location);
			}
			
			if (functionType.returnType()->hasConst()) {
				context.issueDiag(CallReturnTypeIsConstDiag(functionType.returnType()),
						  location);
			}
			
			return addDebugInfo(AST::Value::Call(std::move(value), CastFunctionArguments(context, std::move(args), typeList, location),
							     functionType.returnType()->stripConst()), location);
		}
Пример #2
0
		SEM::Value dissolveLval(Context& context, SEM::Value value, const Debug::SourceLocation& location) {
			assert (canDissolveValue(context, value));
			assert(value.type()->isLval() || (value.type()->isRef() && value.type()->isBuiltInReference() && value.type()->refTarget()->isLval()));
			if (!value.type()->isRef()) {
				value = bindReference(context, std::move(value));
			}
			return CallValue(context, GetSpecialMethod(context, std::move(value), context.getCString("dissolve"), location), {}, location);
		}